Skip to content

fix(mobile): open profile management on the stack that owns the caller - #8708

Merged
iscekic merged 5 commits into
mainfrom
drain/profile-management-stack
Oct 23, 2026
Merged

iscekic merged 5 commits into
mainfrom
drain/profile-management-stack

Conversation

@iscekic

@iscekic iscekic commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — on the Android emulator against the local dev stack, with a local test account (re-run on the final head). Before the change, opening repository defaults from the new-session form and tapping the header Back landed on the Home tab (the repository-defaults screen it opened also kept the bottom tab bar). After the change, the same screen opens on the new-session form's own stack: header Back and system Back both return to the form with the draft text still in the field, and Manage profiles → New profile → Back → Back also returns to the form. The Profile tab's own Profiles row still keeps the tab bar, and Back from there returns to the Profile tab.

What changed

The new-session form ((app)/agent-chat/new) and the agent session screens live on the root (app) Stack, but the profile-management screens they opened resolved inside the Profile tab stack. A push that crosses into the tabs navigator leaves the caller behind it, so Back landed on the tab root instead of the screen that opened the profile screen.

Profile management now takes the Stack it belongs to:

  • src/lib/profile-agent-navigation.ts builds every profile path for either stack (app or profileTab) and defaults to the Profile tab, so existing callers and the Profile tab keep their current routes.
  • src/app/(app)/profile-management/** is a thin route tree on the root stack that renders the existing screens (list, create, repository defaults, profile editor tabs). The Profile tab's own routes are unchanged.
  • Repository defaults (Advanced configuration), Manage profiles (profile picker) and the agent-session profile chip now pass the root stack, so Back returns to the form or the session with its state intact.
  • The profile list, create screen and overview open their own next screen in the stack they were mounted in, so nested profile navigation never jumps stacks.

The root-stack copies also inherit the root stack's content clearance (TabBarLabelContext is null there since the stack itself owns the tab-bar boundary), so their scroll viewport ends at the safe-area edge rather than reserving a bar band that is not rendered.

Verification

  • pnpm --filter kilo-app exec vitest run src/lib/profile-agent-navigation.test.ts src/components/profiles src/components/tab-screen.mounted.test.tsx src/app/\(app\)/agent-chat/profile-picker.mounted.test.tsx src/components/agents/session-detail-content.test.ts — passes.
  • pnpm --filter kilo-app test — 18785 tests pass (2 skipped).
  • pnpm exec tsgo --noEmit and pnpm --filter kilo-app run lint are clean.
  • Emulator, after the change: new-session form → prompt → Advanced configuration → repository defaults: no tab bar on that screen; header Back → form with the prompt; system Back → form with the prompt; Environment → profile picker → Manage profiles → New profile → Back → Back → form with the prompt; Profile tab → Profiles keeps the tab bar and Back returns to the Profile tab.
  • Emulator, bottom clearance with the same screen component: the profiles list opened from the new-session form has its scroll viewport end at y=2337, and the same list opened from the Profile tab at y=2195 (the tab-bar band).

Not exercised on the emulator: the agent-session profile chip, because producing a session with an active profile needs fixtures this run does not have. Its route target is covered by the updated mounted test in session-detail-content.test.ts, which now asserts the root-stack path.

Proxy answers

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

  1. Question: Scope: The same navigator jump also exists where an agent session screen opens a profile (session-detail-content.tsx pushes the tab-stack profile overview). The brief names only the composer's destinations. Include the session screen in this PR?
    Answer: Composer + agent session
    Confidence: 0.65 · Precedent: Fix the root cause and the class of the issue on every affected surface: session 7f3470e0ba6f, "fix class of issue preventing progress"; session 75f8833fe8c1, "fix this for all ... on all surfaces"
  2. Question: Approach: How should the composer's profile screens be hosted in its stack?
    Answer: Parallel app-stack route tree
    Confidence: 0.70 · Precedent: The brief requires that Profile tab entry points keep their current behavior. UX rule (no surprising layout change, best-in-class standard): session 00eb2a1d3e4b, "design and UX MUST BE BEST-IN-CLASS". Keep the wrappers thin and reuse the existing screen components.
  3. Question: Bot review: kilo-code-bot has not created its review check on the merge head d76fc07 (47 minutes, 47/47 CI green, 0 open threads). Its last completed review plus a 0.98 merge recommendation are on the pre-merge head. The host wants a completed bot review of the head. How should I get there?
    Answer: Push a genuine small commit
    Confidence: 0.68 · Precedent: Autonomy: "blocked is not an acceptable end state" (55c9c80332a7) and "if you saw a gap, fix it" (89824a222897). The missing PROFILE_ROOTS rationale comment is a real gap, and adding it gets the bot to review the new head.

The new-session form and agent session screens live on the root `(app)`
Stack, but the profile-management destinations they open (repository
defaults, Manage profiles) resolved inside the Profile tab stack. A push
that crosses into the tabs navigator leaves the caller behind it, so Back
landed on the tab root and the next Back reached the composer only
through the discard guard.

Profile-management routes now take the Stack they belong to. The Profile
tab keeps its own routes and screens; a second route tree at
`(app)/profile-management` serves the root Stack, so Back returns to the
form, the session, or the tab row that opened the screen, with the draft
or the session state intact.

- `profile-agent-navigation` builds every profile path for either stack,
  defaulting to the Profile tab.
- Repository defaults, Manage profiles and the session profile chip pass
  the root stack.
- The profile list, create screen and overview stay in the stack they were
  mounted in for their own pushes.
@iscekic iscekic added drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer labels Oct 23, 2026
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android emulator, local dev stack, local test account. On the fixed build: repository defaults opens from the new-session form without the bottom tab bar, and both the header Back and the system Back return to the form with the typed draft still in the field; the same holds after Environment → profile picker → Manage profiles → New profile → Back → Back.

The draft text in the captures is test data typed for this run.

Repository defaults opened from the new-session form, without the bottom tab bar

New-session form after tapping Back from repository defaults, with the draft text still entered

New-session form after backing out of Manage profiles and the profile create screen, with the draft text still entered

@kilo-code-bot

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

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental change folds the branch onto current main and adds a route-roots doc comment; the root-stack profile route tree, the stack-aware route builders, and the completed call-site audit (new-session, session chip, profile picker, list, create, overview sections) stay consistent, and the removed RootStackProfileScreen wrapper is correctly superseded by the root layout's TabBarLabelContext null.

Assumptions: [INFERENCE] this incremental review compared eae63cf..HEAD (the only commit after the previously reviewed SHA is a docs-only comment, while the merge adopts main's clearance mechanism); the emulator measurements in the PR body were not reproduced here. No typecheck/lint was run because this session is read-only.

Files Reviewed (26 files)
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/[profileId]/index.tsx - no issues
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/index.tsx - no issues
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/new.tsx - no issues
  • apps/mobile/src/app/(app)/agent-chat/profile-picker.mounted.test.tsx - no issues
  • apps/mobile/src/app/(app)/agent-chat/profile-picker.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/agents.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/mcp.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/skills.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/slash-commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/variables.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/new.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/repo-bindings.tsx - no issues
  • apps/mobile/src/components/agents/new-session-screen-body.tsx - no issues
  • apps/mobile/src/components/agents/session-detail-content.test.ts - no issues
  • apps/mobile/src/components/agents/session-detail-content.tsx - no issues
  • apps/mobile/src/components/profiles/new-profile-screen.mounted.test.tsx - no issues
  • apps/mobile/src/components/profiles/new-profile-screen.tsx - no issues
  • apps/mobile/src/components/profiles/profile-overview-screen.test-helpers.ts - no issues
  • apps/mobile/src/components/profiles/profile-overview-screen.tsx - no issues
  • apps/mobile/src/components/profiles/profiles-list-screen.mounted.test.tsx - no issues
  • apps/mobile/src/components/profiles/profiles-list-screen.tsx - no issues
  • apps/mobile/src/lib/profile-agent-navigation.test.ts - no issues
  • apps/mobile/src/lib/profile-agent-navigation.ts - no issues
Previous Review Summaries (2 snapshots, latest commit eae63cf)

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

Previous review (commit eae63cf)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The follow-up makes the bottom clearance stack-aware through TabBarBandContext: every root-stack profile route now declares that no tab bar renders below it, so the shared screens reserve only the safe-area inset while the Profile tab keeps its existing tab-bar clearance. The previously reported dead band is resolved, and the change is covered by two mounted cases.

Assumptions: [INFERENCE] only the incremental change (49ff505..eae63cf) was reviewed in depth; the emulator measurements quoted in the PR body were not reproduced in this environment.

Files Reviewed (14 files)
  • apps/mobile/src/app/(app)/profile-management/[profileId]/agents.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/mcp.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/skills.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/slash-commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/variables.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/new.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/repo-bindings.tsx - no issues
  • apps/mobile/src/components/profiles/root-stack-profile-screen.tsx - no issues
  • apps/mobile/src/components/tab-screen.mounted.test.tsx - no issues
  • apps/mobile/src/components/tab-screen.tsx - no issues
  • apps/mobile/src/lib/tab-bar-clearance.ts - no issues

Previous review (commit 49ff505)

Status: 1 Issues Found | Recommendation: Address before merge

Executive Summary

The stack-owned profile navigation is implemented consistently across the composer, session and Profile tab entry points; the only finding is a layout remnant where the new root-stack profile screens still reserve the tab bar's bottom clearance.

Assumptions: [INFERENCE] the tab-bar clearance gap was derived from TabScreenScrollView/getEffectiveTabBarHeight source (no tab bar is rendered on (app) screens), not from a device run.

Overview

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

SUGGESTION

File Line Issue
apps/mobile/src/components/profiles/profiles-list-screen.tsx 74 Screens mounted on the root (app) stack keep TabScreenScrollView's tab-bar marginBottom, leaving a dead band where no tab bar exists.
Files Reviewed (26 files)
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/[profileId]/index.tsx - no issues
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/index.tsx - no issues
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/profiles/new.tsx - no issues
  • apps/mobile/src/app/(app)/agent-chat/profile-picker.mounted.test.tsx - no issues
  • apps/mobile/src/app/(app)/agent-chat/profile-picker.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/agents.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/mcp.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/skills.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/slash-commands.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/[profileId]/variables.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/index.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/new.tsx - no issues
  • apps/mobile/src/app/(app)/profile-management/repo-bindings.tsx - no issues
  • apps/mobile/src/components/agents/new-session-screen-body.tsx - no issues
  • apps/mobile/src/components/agents/session-detail-content.test.ts - no issues
  • apps/mobile/src/components/agents/session-detail-content.tsx - no issues
  • apps/mobile/src/components/profiles/new-profile-screen.mounted.test.tsx - no issues
  • apps/mobile/src/components/profiles/new-profile-screen.tsx - no issues
  • apps/mobile/src/components/profiles/profile-overview-screen.test-helpers.ts - no issues
  • apps/mobile/src/components/profiles/profile-overview-screen.tsx - no issues
  • apps/mobile/src/components/profiles/profiles-list-screen.mounted.test.tsx - no issues
  • apps/mobile/src/components/profiles/profiles-list-screen.tsx - 1 suggestion
  • apps/mobile/src/lib/profile-agent-navigation.test.ts - no issues
  • apps/mobile/src/lib/profile-agent-navigation.ts - no issues

Reviewed by deepseek-flash-latest · Input: 79.6K · Output: 21.4K · Cached: 1.4M

Review guidance: REVIEW.md from base branch main

The shared profile screens render TabScreenScrollView, which reserves the tab bar's band in the viewport. A screen reused on the root (app) Stack has no bar below it, so that band was empty space at the bottom of every root-stack profile screen.

TabBarBandContext now carries whether a bar is rendered below the screen. The tabs navigator keeps the default, and the root-stack profile routes provide false, so their viewport ends at the safe-area edge. Measured on the emulator with the same screen component: viewport bottom at y=2337 from the new-session form versus y=2195 from the Profile tab.
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Android emulator, same screen component, one build. The profiles list opened from the new-session form ends its scroll viewport at y=2337 (the safe-area edge); the same list opened from the Profile tab ends at y=2195, where the tab-bar band sits. The root-stack copy no longer reserves an empty band at the bottom, and the tab copy is unchanged.

Profiles list opened from the new-session form, its content reaching the bottom safe-area edge

…ent-stack

# Conflicts:
#	apps/mobile/src/components/tab-screen.mounted.test.tsx
#	apps/mobile/src/components/tab-screen.tsx
#	apps/mobile/src/lib/tab-bar-clearance.ts
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Correction after merging main: the earlier note about a local band context no longer applies to this branch. #8509 gives the root stack its own TabBarLabelContext value of null, which already collapses the content clearance to the safe-area inset for every root-stack screen, so this PR dropped its own band plumbing and relies on that. Re-measured on the merged tree with one build and the same screen component: the profiles list opened from the new-session form ends its scroll viewport at y=2337, and the same list from the Profile tab at y=2195.

New-session form after header Back from repository defaults on the merged tree

The two route trees render the same screens; the comment states the rule a caller must follow, at the constant that encodes it.
@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Re-ran the flow on the current head (56b5072): new-session form → prompt → Advanced configuration → repository defaults → header Back returns to the form with the draft, and system Back from repository defaults does the same. The draft text in the captures is test data typed for this run.

New-session form after header Back from repository defaults, with the draft still entered

New-session form after system Back from repository defaults, with the draft still entered

@iscekic

iscekic commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Same run, the frame where the prompt field is in view after system Back from repository defaults: the new-session form still holds the draft. The earlier system-Back capture was scrolled past the field.

New-session form scrolled to the prompt field after system Back from repository defaults, draft still entered

@iscekic iscekic added the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Oct 23, 2026
@iscekic
iscekic enabled auto-merge October 23, 2026 02:31
@iscekic
iscekic added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit d9520d1 Oct 23, 2026
49 checks passed
@iscekic
iscekic deleted the drain/profile-management-stack branch October 23, 2026 12:17
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.

3 participants