Skip to content

fix(mobile): persist the new-session prompt and retry a failed repo prefill - #6771

Merged
iscekic merged 3 commits into
mainfrom
kwf/janitor-mobile-agent-chat-new-session-00e7216c8c
Sep 28, 2026
Merged

iscekic merged 3 commits into
mainfrom
kwf/janitor-mobile-agent-chat-new-session-00e7216c8c

Conversation

@iscekic

@iscekic iscekic commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

Fix proof

A prompt typed on the new-session form before the user.getMe query resolves is never persisted: handlePromptChange skips saveDraft while userId is undefined and no effect re-saves the current

Asserted value: apps/mobile/src/components/agents/new-session-screen-body.tsx. Sense check (model): The changed lines add promptEditedRef and route the seed effect through resolveNewSessionPromptSeedDecision, so a prompt (or cleared prompt) typed before identity resolves gets a 'keep' decision and is what the identity-arrival persist saves, covering the pre-getMe window the claim names.

The scripts were proven on an earlier base, so only the head ran.

Head 434c9a54a140

Head log: backend-assert d71f5c5adb24 exited 0
$ git diff --unified=0 2b2b4faac4eff1d704026c2c251ff23326db390a 434c9a54a140a496c6361b5ce1b4a967bc0facb2 -- apps/mobile/src/components/agents/new-session-screen-body.tsx
diff --git a/apps/mobile/src/components/agents/new-session-screen-body.tsx b/apps/mobile/src/components/agents/new-session-screen-body.tsx
--- a/apps/mobile/src/components/agents/new-session-screen-body.tsx
+++ b/apps/mobile/src/components/agents/new-session-screen-body.tsx
+      return;
+    }
+    const text = promptRef.current;
+    if (text.trim().length > 0 || promptEditedRef.current) {
+      saveDraft(userId, NEW_SESSION_DRAFT_KEY, text);
+    }
+  }, [userId, isCloneEntry, promptRef]);
+

A Continue deep-link repository prefill is consumed permanently when one provider's list errors: reposSettled ignores isError, so with another provider's repositories present and the GitHub query

Asserted value: apps/mobile/src/lib/use-new-session-repos.ts. Sense check (jev): probability 0.9

The scripts were proven on an earlier base, so only the head ran.

Head 434c9a54a140

Head log: backend-assert 3d2b9ad919fe exited 0
$ git diff --unified=0 2b2b4faac4eff1d704026c2c251ff23326db390a 434c9a54a140a496c6361b5ce1b4a967bc0facb2 -- apps/mobile/src/lib/use-new-session-repos.ts
diff --git a/apps/mobile/src/lib/use-new-session-repos.ts b/apps/mobile/src/lib/use-new-session-repos.ts
--- a/apps/mobile/src/lib/use-new-session-repos.ts
+++ b/apps/mobile/src/lib/use-new-session-repos.ts
@@ -39 +39 @@ type UseNewSessionReposResult = {
-  /** True once every provider query has settled and at least one repo is visible. */
+  /** True once every provider query has settled without error and at least one repo is visible. */
@@ -367,0 +368,3 @@ export function useNewSessionRepos({
+    !githubQuery.isError &&
+    !gitlabQuery.isError &&
+    !bitbucketQuery.isError &&

Fix proof

A prompt typed on the new-session form before the user.getMe query resolves is never persisted: handlePromptChange skips saveDraft while userId is undefined and no effect re-saves the current

Asserted value: apps/mobile/src/components/agents/new-session-screen-body.tsx. Sense check (jev): probability 0.9

The scripts were proven on an earlier base, so only the head ran.

Head 4f669045d329

Head log: backend-assert f196555728aa exited 0
$ git diff --unified=0 332f0c033e0781f85b7782c75ee4f2f595a7e2a8 4f669045d329357a6f33bbe75b90020241fa2d10 -- apps/mobile/src/components/agents/new-session-screen-body.tsx
diff --git a/apps/mobile/src/components/agents/new-session-screen-body.tsx b/apps/mobile/src/components/agents/new-session-screen-body.tsx
--- a/apps/mobile/src/components/agents/new-session-screen-body.tsx
+++ b/apps/mobile/src/components/agents/new-session-screen-body.tsx
+      return;
+    }
+    const text = promptRef.current;
+    if (text.trim().length > 0) {
+      saveDraft(userId, NEW_SESSION_DRAFT_KEY, text);
+    }
+  }, [userId, isCloneEntry, promptRef]);
+

A Continue deep-link repository prefill is consumed permanently when one provider's list errors: reposSettled ignores isError, so with another provider's repositories present and the GitHub query

Asserted value: apps/mobile/src/lib/use-new-session-repos.ts. Sense check (jev): probability 0.9

The scripts were proven on an earlier base, so only the head ran.

Head 4f669045d329

Head log: backend-assert 0e793876ab9c exited 0
$ git diff --unified=0 332f0c033e0781f85b7782c75ee4f2f595a7e2a8 4f669045d329357a6f33bbe75b90020241fa2d10 -- apps/mobile/src/lib/use-new-session-repos.ts
diff --git a/apps/mobile/src/lib/use-new-session-repos.ts b/apps/mobile/src/lib/use-new-session-repos.ts
--- a/apps/mobile/src/lib/use-new-session-repos.ts
+++ b/apps/mobile/src/lib/use-new-session-repos.ts
@@ -39 +39 @@ type UseNewSessionReposResult = {
-  /** True once every provider query has settled and at least one repo is visible. */
+  /** True once every provider query has settled without error and at least one repo is visible. */
@@ -367,0 +368,3 @@ export function useNewSessionRepos({
+    !githubQuery.isError &&
+    !gitlabQuery.isError &&
+    !bitbucketQuery.isError &&

Changelog for users

  • A prompt typed on the new-session form before the account loads is now saved, so backgrounding or killing the app keeps the text.
  • A Continue deep-link repository prefill now applies once the failing provider list loads, instead of showing the repository as unavailable.

Changelog for maintainers

  • The settled gate now requires every provider query to finish without error, so one failed list no longer consumes the pending prefill.
  • A new effect saves the current prompt once the account identity arrives; it runs only for non-clone entries with non-empty text.
  • Review the prefill consumption order first: the match must be verified before the applied flag is set.
  • Check the draft save against the clone-entry path, since the effect returns early there and never writes.

E2E proof

A prompt typed on the new-session form before the user.getMe query resolves is never persisted: handlePromptChange skips saveDraft while userId is undefined and no effect re-saves the current prompt when userId later arrives, so backgrounding or killing the app in that window loses the text.

Code trace: apps/mobile/src/components/agents/new-session-screen-body.tsx:566 changed in 925b57d9959a85fa4e7da75ab9f8fc299e3380e2. Sense check (jev): probability 0.91

Changed lines
+  // The composer mounts before `user.getMe` resolves, so a prompt typed in that
+  // window has no account to write under and `handlePromptChange` skips the
+  // save. Persist the current prompt once the identity arrives (and if it
+  // changes), so text typed before the query settled survives a background or
+  // kill rather than waiting for the next keystroke.
+  useEffect(() => {
+    if (isCloneEntry || !userId) {
+      return;
+    }
+    const text = promptRef.current;
+    if (text.trim().length > 0) {
+      saveDraft(userId, NEW_SESSION_DRAFT_KEY, text);
+    }
+  }, [userId, isCloneEntry, promptRef]);
+

A Continue deep-link repository prefill is consumed permanently when one provider's list errors: reposSettled ignores isError, so with another provider's repositories present and the GitHub query failing it reads true, hasAppliedRepo is set before the match is verified, the "repo unavailable" fallback fires, and the prefill is never applied even after the user retries and GitHub repositories load.

Code trace: apps/mobile/src/lib/use-new-session-repos.ts:39 changed in 925b57d9959a85fa4e7da75ab9f8fc299e3380e2. Sense check (model): The added !githubQuery.isError && !gitlabQuery.isError && !bitbucketQuery.isError guards in reposSettled at use-new-session-repos.ts:39 stop it reading true when GitHub errors, fixing the premature prefill consumption the claim describes

Changed lines
-  /** True once every provider query has settled and at least one repo is visible. */
+  /** True once every provider query has settled without error and at least one repo is visible. */
+    !githubQuery.isError &&
+    !gitlabQuery.isError &&
+    !bitbucketQuery.isError &&
Owner request

Fix 2 janitor findings in mobile/agent-chat/new-session. Fix every one; the proof covers each.

  1. A prompt typed on the new-session form before the user.getMe query resolves is never persisted: handlePromptChange skips saveDraft while userId is undefined and no effect re-saves the current prompt when userId later arrives, so backgrounding or killing the app in that window loses the text.
    Trace: apps/mobile/src/components/agents/new-session-screen-body.tsx:561: A prompt typed on the new-session form before the user.getMe query resolves is never persisted: handlePromptChange skips saveDraft while userId is undefined and no effect re-saves the current prompt when userId later arrives, so backgrounding or killing the app in that window loses the text. (janitor area features-workflows).
    Files: apps/mobile/src/components/agents/new-session-screen-body.tsx.
  2. A Continue deep-link repository prefill is consumed permanently when one provider's list errors: reposSettled ignores isError, so with another provider's repositories present and the GitHub query failing it reads true, hasAppliedRepo is set before the match is verified, the "repo unavailable" fallback fires, and the prefill is never applied even after the user retries and GitHub repositories load.
    Trace: apps/mobile/src/lib/use-new-session-repos.ts:364: A Continue deep-link repository prefill is consumed permanently when one provider's list errors: reposSettled ignores isError, so with another provider's repositories present and the GitHub query failing it reads true, hasAppliedRepo is set before the match is verified, the "repo unavailable" fallback fires, and the prefill is never applied even after the user retries and GitHub repositories load. (janitor area features-workflows).
    Files: apps/mobile/src/lib/use-new-session-repos.ts.

@iscekic iscekic added the kwf-janitor Admitted to the workflow from a janitor finding label Sep 27, 2026
@iscekic iscekic self-assigned this Sep 27, 2026
Comment thread apps/mobile/src/components/agents/new-session-screen-body.tsx
@kilo-code-bot

kilo-code-bot Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • apps/mobile/src/components/agents/new-session-prompt-seed.ts
  • apps/mobile/src/components/agents/new-session-prompt-seed.test.ts
  • apps/mobile/src/components/agents/new-session-screen-body.tsx
Previous Review Summaries (2 snapshots, latest commit 4f66904)

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

Previous review (commit 4f66904)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit resolves the previously flagged prompt-persistence defect: the draft-seed effect now preserves the route-owned prompt when the draft load re-settles on an identity change, so the persist effect saves the pre-identity text under the settled identity. No new issues found in the changed lines.

Files Reviewed (2 files)
  • apps/mobile/src/components/agents/new-session-screen-body.tsx
  • apps/mobile/src/lib/use-new-session-repos.ts

Previous review (commit 4c5d521)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The new prompt-persistence effect in the mobile new-session screen can still drop text typed before the account loads, because an earlier effect clears promptRef in the same commit when the identity arrives late.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/components/agents/new-session-screen-body.tsx 571 Identity-arrival save reads an already-cleared promptRef when the draft state had already settled before the identity arrived, so pre-identity text is not persisted.
Files Reviewed (2 files)
  • apps/mobile/src/components/agents/new-session-screen-body.tsx - 1 issue
  • apps/mobile/src/lib/use-new-session-repos.ts - 0 issues

Notes: The reposSettled change now matches the documented settled contract in new-session-prefill.ts ("finished loading, without error, and non-empty"); react-query's setQueryData/isError retry interaction could not be executed in read-only mode, so it was not flagged.


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

The seed effect cleared the route-owned prompt when the draft load
re-settled on an identity change, even though a `settled` seed does not
remount the uncontrolled input. That desynced the visible text from
`promptRef`/hasPrompt: the prompt typed before the identity arrived was
not persisted and Start stayed disabled. Preserve a non-empty route-owned
prompt unless the input remounts (a `restore` seed).
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 27, 2026
@iscekic iscekic added merge-by-human the merge bot routed this PR to a human merge-by-bot and removed human-ready The PR is ready for human review. merge-by-human the merge bot routed this PR to a human labels Sep 27, 2026
@iscekic
iscekic marked this pull request as draft September 28, 2026 08:42
@iscekic
iscekic marked this pull request as ready for review September 28, 2026 08:46
@iscekic
iscekic marked this pull request as draft September 28, 2026 08:54
@iscekic
iscekic marked this pull request as ready for review September 28, 2026 09:06
@iscekic
iscekic marked this pull request as draft September 28, 2026 09:19
@iscekic
iscekic marked this pull request as ready for review September 28, 2026 09:30
Comment thread apps/mobile/src/components/agents/new-session-screen-body.tsx Outdated
@iscekic
iscekic marked this pull request as draft September 28, 2026 18:41
The seed effect only preserved a pre-identity edit when the route-owned prompt was non-empty, so clearing the field to empty before the identity resolved let the identity-bound draft load remount the older saved draft over the clear. Track any pre-identity edit, including a clear, and settle the seed in place instead of restoring; persist the explicit empty edit on identity arrival so the stored draft cannot resurface. The decision is extracted to a pure helper with a regression test for typing, clearing, then resolving the identity with an existing saved draft.
@iscekic
iscekic marked this pull request as ready for review September 28, 2026 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kwf-janitor Admitted to the workflow from a janitor finding merge-by-bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants