Skip to content

fix(mobile): honor a session's organization on notification tap and default to an organization at login - #6611

Merged
iscekic merged 3 commits into
mainfrom
kwf/org-context-on-login-and-push-9f6d
Sep 24, 2026
Merged

iscekic merged 3 commits into
mainfrom
kwf/org-context-on-login-and-push-9f6d

Conversation

@iscekic

@iscekic iscekic commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Changelog for users

  • Tapping a session notification now switches the app to the organization that session belongs to.
  • The session list behind the opened session is populated instead of empty.
  • A notification that carries no organization leaves the current selection unchanged.
  • The app starts on your first organization instead of Personal when you have not chosen one yet.
  • An explicit Personal choice is remembered across relaunches.
  • A previously chosen organization still wins over the default.
  • When the organization list cannot be loaded, the app stays on Personal and remains usable.
  • Features that read the saved selection now use the same default organization the app shows.

Changelog for maintainers

  • apps/mobile/src/lib/organization-context.tsx:146 — accepted: a paused (offline) organizations list never fetches, so waiting on it left isLoaded false forever; the provider now settles on Personal and stays usable, keeps the default fence armed, and applies the first organization when the list arrives.
  • apps/mobile/src/lib/organization-context.tsx:212 — accepted: choosing Personal while already on an auto-resolved Personal returned early without recording the choice, so a later list with organizations moved the person back on relaunch; the explicit-Personal marker is now written even when the published id does not change.
  • services/session-ingest/.dev.vars.example:1 — accepted: the example carried DIRECT_INGEST_PERCENT="100" for the E2E session fixture, putting verification-only runtime config in the product diff; it is restored to "0".
  • apps/mobile/src/lib/organization-context.tsx:139 — accepted: the default organization reached React state only, so glanceable scope, widget actions, voice input, and tool-summary translation kept resolving Personal from the stored key; the default now persists through the existing save path.
  • cloud_agent_session push data carries an optional organizationId; absent means Personal, so old producers still validate in a rolling deploy, and both server builders plus the app-posted raise attach the session's organization.
  • Pending deep links carry organizationId; records written before this release default to null and switch nothing; the single consumer switches before navigating — check this effect first for race risk.
  • A second storage key records an explicit Personal choice, so an absent organization key now means "not chosen yet"; login and sign-out clear the marker, and the provider resolves its default from the shared organizations list under the existing auth-epoch and generation fence, writing neither key for an empty or failed list.
  • Proof update: the new run re-verifies that fresh sign-in lands on the first organization and that an explicit Personal choice survives a relaunch, both re-read from the predecessor run's digests rather than re-run, and adds the offline launch scenario; these replace the earlier fresh-sign-in proof that only showed the selector, while the stored-organization relaunch proof is unchanged.

E2E proof

e1-org-context.png

p1.png

p1p.png

p1r.png

p2.png

p2-selector.png

e12-03-selected-zebra.png

e12-04-after-relaunch-zebra.png

e12-01-default-acme.png

e12-02-selector.png

e11-03-selected-personal.png

e4.png

e7-selector.png

e7-agents.png

e1-profile.png

e1-home-ux.png

e8-agents-personal-history.png

e8-agents-org-history.png

e8-session-screen.png

e8-profile-org-acme.png

e3-personal-empty-list.png

e3.png

e3-list.png

e3-personal-home.png

e9-selector-org.png

e10.png

e10-cold-launch.png

e10-list.png

e1.png

e1-home.png

e2-select-second2.png

Owner request

Surface: mobile-app

Fix the organization context in two places. The owner reported both as user reports.

Report A. A person gets a session push, taps it, the session opens, they go back to the list,
and the list is empty. Days later they realise they had to switch to an organization first. A
notification tap must put the app in the context the session belongs to.

Report B. The app should pick an organization by default at login. Today it always lands on
Personal.

Report A alone would still leave the app on Personal after a fresh login, so both belong in one
change. The two parts touch the same provider, so one item owns them.

Part A — a notification tap switches to the session's organization

What is true today

The push already knows the organization and then drops it.

  • apps/mobile/src/lib/needs-input-notification.ts:54 and :191 — the notification row carries
    organizationId, and :242 compares it when deciding whether a repost changed anything.
  • apps/mobile/src/lib/needs-input-notification.ts:274-287 — pushDataForRow builds the push
    data and omits organizationId:
    return { type: 'cloud_agent_session', cliSessionId: row.sessionId,
             category: 'attention', attentionKind: row.kind, ...prUrl };
    
  • packages/notifications/src/push-data.ts — the cloud_agent_session variant carries
    cliSessionId, category, attentionKind, prUrl and no organization, while the low_balance
    and spend_alert variants beside it do carry organizationId. So the field is already an
    established idea in this schema, just missing here.
  • Server producers: services/session-ingest/src/queue-consumer.ts:460 calls
    env.NOTIFICATIONS.sendCloudAgentSessionNotification(pushParams);
    services/session-ingest/src/remote-session-notifications.ts:113-131 builds those params;
    services/notifications/src/lib/cloud-agent-session-push.ts turns them into the Expo blob; the
    param type is SendCloudAgentSessionNotificationParams in
    packages/notifications/src/rpc-schemas.ts. The session scope id is already read from the
    session row. services/cloud-agent-next/src/session/message-settlement-outbox.ts is a second
    producer — check it too.
  • apps/mobile/src/lib/notification-actions.ts:236-274 — the tap handler stashes a deep link and
    nothing else. apps/mobile/src/lib/deep-link-launch.ts carries the pending deep link plus a
    pendingDeepLinkUserId; apps/mobile/src/app/_layout.tsx:780-795 is the single gated consumer
    that navigates.

Required result

  • Carry the organization with the notification, end to end: the shared schema, both server
    producers, and the mobile local publisher.
  • Make the new field optional in the schema, exactly as the file's own comment requires
    ("Optional everywhere it appears so old producers in a rolling deploy still validate"). A push
    with no organization must parse and must not switch anything.
  • On tap, switch the organization before the session route fetches, then navigate. The switch
    and the navigation must not race: the consumer that owns the navigation
    (_layout.tsx:780-795) is the place to apply it, and the organization id must travel with the
    pending deep link the same way pendingDeepLinkUserId already does.
  • Use the existing setOrganizationId from apps/mobile/src/lib/organization-context.tsx. Do not
    invent a second switch path. Its side effects — ending the prior organization's privacy snapshot
    and unregistering the prior organization's activity tokens — are correct for this transition.
  • A push for a Personal session must leave Personal selected.
  • The session must be reachable from the list after the switch. That is the reported symptom, so
    prove it, not just the navigation.

Part B — a default organization at login

What is true today

apps/mobile/src/lib/organization-context.tsx:53-72 — restore() reads
ORGANIZATION_STORAGE_KEY from SecureStore, and stored ?? null means Personal:

// Existing installs store a raw organization string; an absent value means
// Personal. Keep both forms until those installations and records cannot exist.
const stored = await SecureStore.getItemAsync(ORGANIZATION_STORAGE_KEY);
activeId.current = stored ?? null;

So a fresh install, or any account whose selection was never written, lands on Personal. The
organization list is available at apps/mobile/src/lib/hooks/use-organization-queries.ts:32
(trpc.organizations.list.queryOptions()).

Required result

The owner chose this rule. Implement exactly it:

restore():
  stored = SecureStore.getItemAsync(ORGANIZATION_STORAGE_KEY)
  if (stored)                     -> use it
  else if (orgs.length > 0)       -> orgs[0].id
  else                            -> Personal (null)

Constraints:

  • An explicit stored choice always wins. Never override a stored selection with the default.
  • An explicit Personal choice must survive a relaunch. Today null and "not chosen yet" are
    the same value: setOrganizationId(null) deletes the key
    (organization-context.tsx:77-96 → deleteAccountMetadata), so the key is absent on the next
    launch and the new default rule would move the person back to an organization they deliberately
    left. Separate the two states. A settled representation that can express "Personal, chosen" is
    required — the file's own comment already flags that both forms must be handled ("Keep both forms
    until those installations and records cannot exist"), so read the legacy forms and write the new
    one.
  • Do not block first paint on the organization list. If the list is still loading, isLoaded must
    not wait on the network forever; resolve the default when the list arrives, and keep an explicit
    stored choice available immediately.
  • If the list request fails, keep Personal and keep the app usable. Do not spin, and do not show an
    error for a default that was only a convenience. Report the failure the way the provider already
    reports restore and save errors (error: 'restore' | 'save').
  • The existing org fence stays: a selected organization missing from a successful organizations.list
    is a confirmed lost organization (apps/mobile/src/lib/glanceable/org-fence.ts). A default chosen
    from that same list can never trip it.
  • Keep the auth-epoch fencing and the generation counter in the provider. Every new read must be
    fenced exactly like the existing ones, so a sign-out or a newer sign-in during the list fetch
    cannot publish a stale organization.

Files

  • apps/mobile/src/lib/organization-context.tsx — part B, and the switch part A calls.
  • apps/mobile/src/lib/hooks/use-organization-queries.ts — the list the default reads.
  • apps/mobile/src/lib/needs-input-notification.ts — part A, the dropped field.
  • apps/mobile/src/lib/notification-actions.ts and deep-link-launch.ts — part A, the tap path.
  • apps/mobile/src/app/_layout.tsx — part A, the single deep-link consumer.
  • packages/notifications/src/push-data.ts and packages/notifications/src/rpc-schemas.ts — the
    shared contract.
  • services/notifications/src/lib/cloud-agent-session-push.ts,
    services/session-ingest/src/remote-session-notifications.ts,
    services/session-ingest/src/queue-consumer.ts,
    services/cloud-agent-next/src/session/message-settlement-outbox.ts — the producers.

Do not edit a file outside this list.

Proof

Part A needs a real push, because the whole defect is about what a tap does.

  • Deliver a session push for a session that belongs to an organization while the app is on Personal.
    The mobile runbook has sim-tool.sh ... push payload.json for iOS and the needs-input fixture for
    a real session (e2e/needs-input.sh <email> new). Build the payload with the new
    organizationId field.
  • Tap it. Prove the app lands on the session and the list behind it shows the session. Quote the
    decisive log lines, and capture the screen. The empty list is the reported symptom, so the list
    after the switch is the proof.
  • Negative case: a push with no organizationId must parse and must leave the selection unchanged.
  • Part B needs a login, not a push. Sign in on a fresh account, or clear the stored key, and prove
    the app lands on the first organization with the list populated. Capture the screen.
  • Prove an explicit Personal choice survives a relaunch: select Personal, relaunch, and prove the
    app is still on Personal. Capture both states.
  • Prove a stored organization choice still wins over the default.

Keep pnpm --filter @kilocode/mobile test green, plus the mounted suite the section runbook names.
Add tests that fail on the old behaviour: a cloud_agent_session push carrying an organization must
switch the selection; a push without one must not.

E2E proof — log excerpts

[e1] Offline launch stays usable on Personal: with the device offline and no sto -> pass :: jev read the digest: pass (confidence 0.99)
/home/igor_kilocode_ai/.local/share/kwf/sections/kwf-fix-review-1381/e2e-mobile-app/scripted-e1.log
android.widget.TextView Find and remediate vulnerabilities tappable [171,907][953,944]
android.widget.TextView REVIEWS tappable [37,1027][1045,1071]
android.widget.Button PR Review, Review pull requests on mobile tappable [37,1099][1043,1241]
android.widget.TextView PR Review tappable [171,1127][953,1173]
android.widget.TextView Review pull requests on mobile tappable [171,1177][953,1214]
android.widget.TextView ORGANIZATION tappable [37,1296][1045,1340]
android.widget.Button View organization, Acme Corp tappable [37,1368][1043,1511]
android.widget.TextView View organization tappable [171,1396][953,1442]
android.widget.TextView Acme Corp tappable [171,1446][953,1483]
android.widget.TextView APP tappable [37,1565][1045,1609]
android.widget.Button Preferences, Appearance, notifications, thinking, and screen behavior tappable [37,1637][1043,1781]
android.widget.TextView Preferences tappable [171,1665][953,1711]
android.widget.TextView Appearance, notifications, thinking, and screen behavior tappable [171,1715][953,1752]
android.widget.Button Tutorial tappable [37,1808][1043,1942]
android.widget.TextView Tutorial tappable [171,1852][953,1898]
android.widget.TextView LINKED ACCOUNTS tappable [37,1997][1045,2041]
android.widget.TextView Email tappable [171,2097][1017,2143]
android.widget.TextView e2e-mobile-kwf-fix-review-1381-android@example.com tappable [171,2147][1017,2184]
android.widget.Button Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.widget.Button Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView AGENTS tappable [373,2281][707,2320]
android.widget.Button Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
android.widget.TextView PROFILE tappable [733,2281][1067,2320]

Review fixes — head 12ef2ff

apps/mobile/src/lib/organization-context.tsx:92 — a marker-read failure discarded a readable saved organization

cd apps/mobile && pnpm exec vitest run src/lib/organization-context.mounted.test.tsx

 Test Files  1 passed (1)
      Tests  24 passed (24)

honors a saved organization when the Personal marker read fails failed before the fix with waitFor: condition not met after 50 attempts (the marker rejection took the catch and published error: 'restore' with isLoaded false); it passes with the organization key read on its own. reports a restore error when the marker read fails with no saved organization pins the retained error.

apps/mobile/src/lib/notification-actions.ts:261 — a session notification could restore and switch organization under another account

cd apps/mobile && pnpm exec vitest run src/lib/notification-actions.test.ts src/lib/notifications.test.ts

 Test Files  2 passed (2)
      Tests  169 passed (169)

Before the fix, never restores an anonymous session tap for another account failed with expected { href: "/(app)/agent-chat/ses_1?via=push", organizationId: "org-9" } to be null, and drops a session tap captured with no account identity when the account settles signed out plus drops a session push captured before a signed-out settle failed because the anonymous destination stayed stashed. A session destination now carries the pending slot's existing sessionBound identity binding.

Full suite: cd apps/mobile && pnpm test

 Test Files  1021 passed (1021)
      Tests  15784 passed (15784)

@iscekic
iscekic marked this pull request as draft September 23, 2026 03:15
Comment thread apps/mobile/src/lib/organization-context.tsx
@kilo-code-bot

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

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental review of the 7 files changed since 5fe7bdf finds no new defects: the cross-account session-notification finding is fixed by binding the destination to an account (sessionBound), and the Personal-marker read is now isolated so a marker failure cannot discard a saved organization.

Files Reviewed (7 files)
  • apps/mobile/src/lib/deep-link-launch.ts
  • apps/mobile/src/lib/notification-actions.test.ts
  • apps/mobile/src/lib/notification-actions.ts
  • apps/mobile/src/lib/notifications.test.ts
  • apps/mobile/src/lib/notifications.ts
  • apps/mobile/src/lib/organization-context.mounted.test.tsx
  • apps/mobile/src/lib/organization-context.tsx

Verified Fixes

  • notification-actions.ts — session pushes now carry sessionBound: true, so an anonymous (signed-out) capture is dropped and a persisted anonymous record is never restored for another account; notifications.ts cold-start body tap shares the same helper.
  • organization-context.tsx — the organization key is read first and the Personal marker only when it is absent, so a marker-read rejection no longer discards a readable saved organization.
Previous Review Summaries (4 snapshots, latest commit 5fe7bdf)

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

Previous review (commit 5fe7bdf)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The fallback full review of the 26 changed files at commit 5fe7bdf finds no new defects. The earlier circular-import and default-organization persistence findings are fixed at this HEAD, and the declined legacy explicit-Personal observation is unchanged.

Files Reviewed (26 files)
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/context-control.mounted.test.tsx
  • apps/mobile/src/components/profile-credits-card.mounted.test.tsx
  • apps/mobile/src/lib/auth/auth-context.lifecycle.test.tsx
  • apps/mobile/src/lib/auth/auth-context.tsx
  • apps/mobile/src/lib/deep-link-launch.mounted.test.tsx
  • apps/mobile/src/lib/deep-link-launch.test.ts
  • apps/mobile/src/lib/deep-link-launch.ts
  • apps/mobile/src/lib/hooks/use-organization-queries.ts
  • apps/mobile/src/lib/hooks/use-organizations-list.ts
  • apps/mobile/src/lib/needs-input-notification.test.ts
  • apps/mobile/src/lib/needs-input-notification.ts
  • apps/mobile/src/lib/notification-actions.test.ts
  • apps/mobile/src/lib/notification-actions.ts
  • apps/mobile/src/lib/notifications.test.ts
  • apps/mobile/src/lib/notifications.ts
  • apps/mobile/src/lib/organization-context.mounted.test.tsx
  • apps/mobile/src/lib/organization-context.test.ts
  • apps/mobile/src/lib/organization-context.tsx
  • apps/mobile/src/lib/storage-keys.ts
  • packages/notifications/src/push-data.test.ts
  • packages/notifications/src/push-data.ts
  • services/notifications/src/lib/agent-session-notification-push.test.ts
  • services/notifications/src/lib/agent-session-notification-push.ts
  • services/notifications/src/lib/cloud-agent-session-push.ts
  • services/notifications/src/lib/notifications-service-cloud-agent.test.ts

Previous review (commit 61673b1)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (27 files)
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/context-control.mounted.test.tsx
  • apps/mobile/src/components/profile-credits-card.mounted.test.tsx
  • apps/mobile/src/lib/auth/auth-context.lifecycle.test.tsx
  • apps/mobile/src/lib/auth/auth-context.tsx
  • apps/mobile/src/lib/deep-link-launch.mounted.test.tsx
  • apps/mobile/src/lib/deep-link-launch.test.ts
  • apps/mobile/src/lib/deep-link-launch.ts
  • apps/mobile/src/lib/hooks/use-organization-queries.ts
  • apps/mobile/src/lib/hooks/use-organizations-list.ts
  • apps/mobile/src/lib/needs-input-notification.test.ts
  • apps/mobile/src/lib/needs-input-notification.ts
  • apps/mobile/src/lib/notification-actions.test.ts
  • apps/mobile/src/lib/notification-actions.ts
  • apps/mobile/src/lib/notifications.test.ts
  • apps/mobile/src/lib/notifications.ts
  • apps/mobile/src/lib/organization-context.mounted.test.tsx
  • apps/mobile/src/lib/organization-context.test.ts
  • apps/mobile/src/lib/organization-context.tsx
  • apps/mobile/src/lib/storage-keys.ts
  • packages/notifications/src/push-data.test.ts
  • packages/notifications/src/push-data.ts
  • services/notifications/src/lib/agent-session-notification-push.test.ts
  • services/notifications/src/lib/agent-session-notification-push.ts
  • services/notifications/src/lib/cloud-agent-session-push.ts
  • services/notifications/src/lib/notifications-service-cloud-agent.test.ts
  • services/session-ingest/.dev.vars.example

The previously reported circular import is resolved: useOrganizationsList now lives in use-organizations-list.ts, which imports only auth-context/trpc, so the provider no longer imports a module that imports it back. The default-organization persistence fix is present, and the remaining legacy explicit-Personal observation was declined by the author as matching the owner's stated rule (absent key = not chosen yet -> first organization). No new issues in the changed code.

Previous review (commit 0a88468)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The prior storage-persistence finding is fixed; the remaining observations are non-blocking: a newly introduced circular import between the organization provider and its query hook module, and the one-time migration of pre-existing explicit-Personal selections to the first organization.

Overview

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

SUGGESTION

File Line Issue
apps/mobile/src/lib/organization-context.tsx 18 New circular import: organization-context.tsx imports useOrganizationsList from use-organization-queries.ts, which imports useOrganization back from organization-context.tsx. Safe at runtime today, but apps/mobile/.oxlintrc.json sets import/no-cycle to error.
apps/mobile/src/lib/organization-context.tsx 98 An absent organization key with no Personal marker is treated as "not chosen yet", so installations that explicitly chose Personal before this release are silently switched to organizations[0] on upgrade.
Files Reviewed (26 files)
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/context-control.mounted.test.tsx
  • apps/mobile/src/components/profile-credits-card.mounted.test.tsx
  • apps/mobile/src/lib/auth/auth-context.lifecycle.test.tsx
  • apps/mobile/src/lib/auth/auth-context.tsx
  • apps/mobile/src/lib/deep-link-launch.mounted.test.tsx
  • apps/mobile/src/lib/deep-link-launch.test.ts
  • apps/mobile/src/lib/deep-link-launch.ts
  • apps/mobile/src/lib/hooks/use-organization-queries.ts
  • apps/mobile/src/lib/needs-input-notification.test.ts
  • apps/mobile/src/lib/needs-input-notification.ts
  • apps/mobile/src/lib/notification-actions.test.ts
  • apps/mobile/src/lib/notification-actions.ts
  • apps/mobile/src/lib/notifications.test.ts
  • apps/mobile/src/lib/notifications.ts
  • apps/mobile/src/lib/organization-context.mounted.test.tsx
  • apps/mobile/src/lib/organization-context.test.ts
  • apps/mobile/src/lib/organization-context.tsx
  • apps/mobile/src/lib/storage-keys.ts
  • packages/notifications/src/push-data.test.ts
  • packages/notifications/src/push-data.ts
  • services/notifications/src/lib/agent-session-notification-push.test.ts
  • services/notifications/src/lib/agent-session-notification-push.ts
  • services/notifications/src/lib/cloud-agent-session-push.ts
  • services/notifications/src/lib/notifications-service-cloud-agent.test.ts
  • services/session-ingest/.dev.vars.example

Fix these issues in Kilo Cloud

Previous review (commit 5588aa8)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

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

WARNING

File Line Issue
apps/mobile/src/lib/organization-context.tsx 139 Resolved default organization is published to React context but not written to ORGANIZATION_STORAGE_KEY, so non-React SecureStore readers (glanceable scope, widget actions, voice input, tool-summary translation) stay scoped to Personal while the app is on the default org.
Files Reviewed (26 files)
  • apps/mobile/src/app/_layout.tsx - 0 issues
  • apps/mobile/src/components/context-control.mounted.test.tsx - 0 issues
  • apps/mobile/src/components/profile-credits-card.mounted.test.tsx - 0 issues
  • apps/mobile/src/lib/auth/auth-context.lifecycle.test.tsx - 0 issues
  • apps/mobile/src/lib/auth/auth-context.tsx - 0 issues
  • apps/mobile/src/lib/deep-link-launch.mounted.test.tsx - 0 issues
  • apps/mobile/src/lib/deep-link-launch.test.ts - 0 issues
  • apps/mobile/src/lib/deep-link-launch.ts - 0 issues
  • apps/mobile/src/lib/hooks/use-organization-queries.ts - 0 issues
  • apps/mobile/src/lib/needs-input-notification.test.ts - 0 issues
  • apps/mobile/src/lib/needs-input-notification.ts - 0 issues
  • apps/mobile/src/lib/notification-actions.test.ts - 0 issues
  • apps/mobile/src/lib/notification-actions.ts - 0 issues
  • apps/mobile/src/lib/notifications.test.ts - 0 issues
  • apps/mobile/src/lib/notifications.ts - 0 issues
  • apps/mobile/src/lib/organization-context.mounted.test.tsx - 0 issues
  • apps/mobile/src/lib/organization-context.test.ts - 0 issues
  • apps/mobile/src/lib/organization-context.tsx - 1 issue
  • apps/mobile/src/lib/storage-keys.ts - 0 issues
  • packages/notifications/src/push-data.test.ts - 0 issues
  • packages/notifications/src/push-data.ts - 0 issues
  • services/notifications/src/lib/agent-session-notification-push.test.ts - 0 issues
  • services/notifications/src/lib/agent-session-notification-push.ts - 0 issues
  • services/notifications/src/lib/cloud-agent-session-push.ts - 0 issues
  • services/notifications/src/lib/notifications-service-cloud-agent.test.ts - 0 issues
  • services/session-ingest/.dev.vars.example - 0 issues

Fix these issues in Kilo Cloud


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

Review guidance: REVIEW.md from base branch main

iscekic added a commit that referenced this pull request Sep 23, 2026
@iscekic
iscekic force-pushed the kwf/org-context-on-login-and-push-9f6d branch from cb5aa96 to 0a88468 Compare September 23, 2026 05:23
@iscekic
iscekic marked this pull request as ready for review September 23, 2026 05:43
Comment thread apps/mobile/src/lib/organization-context.tsx Outdated
Comment thread apps/mobile/src/lib/organization-context.tsx
@iscekic
iscekic marked this pull request as draft September 23, 2026 06:08
iscekic added a commit that referenced this pull request Sep 23, 2026
@iscekic
iscekic force-pushed the kwf/org-context-on-login-and-push-9f6d branch from c824acd to 61673b1 Compare September 23, 2026 06:44
@iscekic
iscekic marked this pull request as ready for review September 23, 2026 06:55
@iscekic

iscekic commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

kilo-review — independent audit of the published diff.

Status: 3 Issues

File Line Issue
apps/mobile/src/lib/organization-context.tsx 146 An offline (paused) organizations.list leaves isLoaded false forever instead of resolving to Personal, contradicting the requirement that an unloadable list keeps the app on Personal and usable.
apps/mobile/src/lib/organization-context.tsx 212 Selecting Personal while already on an auto-resolved Personal is a no-op, so the explicit-Personal marker is not written and the choice is lost on the next launch once an organization exists.
services/session-ingest/.dev.vars.example 1 DIRECT_INGEST_PERCENT is flipped to "100" for the E2E session fixture, committing verification-only runtime config into the product diff without owner permission.

@iscekic
iscekic marked this pull request as draft September 23, 2026 07:45
@iscekic

iscekic commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Accepted. Pushed 8eb093e (kwf kwf-fix-review-1381).

What changed:

  • apps/mobile/src/lib/organization-context.tsx:146 — accepted: a paused (offline) organizations list never fetches, so waiting on it left isLoaded false forever; the provider now settles on Personal and stays usable, keeps the default fence armed, and applies the first organization when the list arrives.
  • apps/mobile/src/lib/organization-context.tsx:212 — accepted: choosing Personal while already on an auto-resolved Personal returned early without recording the choice, so a later list with organizations moved the person back on relaunch; the explicit-Personal marker is now written even when the published id does not change.
  • services/session-ingest/.dev.vars.example:1 — accepted: the example carried DIRECT_INGEST_PERCENT="100" for the E2E session fixture, putting verification-only runtime config in the product diff; it is restored to "0".
  • apps/mobile/src/lib/organization-context.tsx:139 — accepted: the default organization reached React state only, so other readers of the stored key kept resolving Personal; the default now persists through the existing save path.
  • cloud_agent_session push data carries an optional organizationId; absent means Personal, so old producers still validate in a rolling deploy, and both server builders plus the app-posted raise attach the session's organization.
  • Pending deep links carry organizationId; records written before this release default to null and switch nothing; the single consumer switches before navigating — check this effect first for race risk.
  • A second storage key records an explicit Personal choice, so an absent organization key now means "not chosen yet"; login and sign-out clear the marker so the next account on the device resolves its own default.
  • The provider resolves its default from the shared organizations list, fenced by the auth epoch and generation counter; an empty or failed list writes neither storage key.

@iscekic
iscekic force-pushed the kwf/org-context-on-login-and-push-9f6d branch from e9380a0 to 5fe7bdf Compare September 23, 2026 14:48
@iscekic
iscekic marked this pull request as ready for review September 23, 2026 15:08
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 23, 2026
@iscekic iscekic self-assigned this Sep 23, 2026
Comment thread apps/mobile/src/lib/notification-actions.ts Outdated
Comment thread apps/mobile/src/lib/organization-context.tsx Outdated
… fails

The restore path read the organization key and the Personal marker with one
`Promise.all`, so a marker-read rejection discarded a readable saved
organization: the restore reported an error and left the provider unresolved.
The organization key is now read on its own, since it stands alone, and the
marker is only consulted when no organization is stored. A marker failure with
nothing stored stays the existing restore error.

#6611
…hat captured it

A session notification stashed its destination as an ordinary notification, so
a record captured before the account settled stayed account-independent: it
could later restore (or survive a sign-in) for a different account and switch
the app to the session's organization, which the pending-slot consumer applies
without a membership check.

Session destinations now carry the slot's existing `sessionBound` identity
binding, so a capture with no account identity is dropped and a record bound to
one account never restores for another. The organization still rides along for
the account that owns the session.

#6611
@iscekic
iscekic merged commit d84323a into main Sep 24, 2026
34 checks passed
@iscekic
iscekic deleted the kwf/org-context-on-login-and-push-9f6d branch September 24, 2026 14:30
iscekic pushed a commit to Kilo-Org/kilocode that referenced this pull request Sep 26, 2026
…4554)

## Automated docs sync — 2026-09-25

This PR keeps kilo.ai/docs in sync with features merged to [Kilo-Org/cloud](https://github.com/Kilo-Org/cloud) and [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode). Every change below links to the merged PR it documents.

- Window: `2026-09-24T07:08:33.639Z` → `2026-09-25T07:05:29.302Z`
- Verification (docs build + tests): **passing**

### Surface: `cloud-mobile`

- Assignees / requested reviewers: @iscekic and @eshurakov
- Derivation: Derived from the repository layout. A product surface is a package under packages/ that ships a distinct client, plugin, backend, or hosted service: cli = packages/opencode/ + packages/tui/ + packages/server/ + packages/sdk/ + packages/plugin/; vscode = packages/kilo-vscode/ + packages/kilo-web-ui/ + packages/kilo-ui/; jetbrains = packages/kilo-jetbrains/; gateway = packages/kilo-gateway/; web = packages/kilo-console/ + packages/kilo-indexing/ + packages/kilo-memory/ + packages/kilo-sandbox/. Docs route from the IA tree packages/kilo-docs/pages/ plus docs/jetbrains-vscode-settings-parity.md: each surface lists the pages sections that document it, and the per-platform pages under packages/kilo-docs/pages/code-with-ai/platforms/ map to the matching extension surface (the vscode/ directory to vscode, jetbrains.md to jetbrains). A doc path belongs to the surface with the longest matching prefix; a path that matches none of those prefixes falls to `other` (the explicit other prefixes are listed under other.docs). The cloud surfaces are derived the same way from the Kilo-Org/cloud layout: cloud-mobile = apps/mobile/, cloud-web = apps/web/, cloud-extension = apps/extension/, and cloud-agent = the cloud-agent packages under packages/ (packages/cloud-agent-sdk/ + packages/cloud-agent-profile/). A cloud source names its repository while a bare string still means this repository. The pages under packages/kilo-docs/pages/collaborate/ document the cloud web app (app.kilo.ai: teams dashboard, billing, SSO, adoption dashboard), so they route to cloud-web. No page under packages/kilo-docs/pages/ documents the browser side-panel extension yet, so cloud-extension lists no docs prefix.
- Map: `.github/docs-sync/surfaces.json`
- Surface map: `cli`, `vscode`, `jetbrains`, `gateway`, `web`, `cloud-mobile`, `cloud-web`, `cloud-extension`, `cloud-agent`, `other`
- Source prefixes: `apps/mobile/` (Kilo-Org/cloud)
- Doc prefixes: `packages/kilo-docs/pages/code-with-ai/platforms/mobile.md`
- Paths that fall to `other`: `packages/kilo-docs/pages/community/`, `packages/kilo-docs/pages/kiloclaw/`, `packages/kilo-docs/pages/contributing/`, `packages/kilo-docs/LEARNINGS.md`, `docs/`
- Reviewers are ranked from `Kilo-Org/cloud`; the workflow needs a token with `contents: read` on that repository (repository secret `CROSS_REPO_ACCESS_TOKEN`, exposed to the upsert step as `CLOUD_REPO_TOKEN`).
- How the two were computed: Reviewers for `cloud-mobile` are ranked from `Kilo-Org/cloud` git history over `apps/mobile/` (a commit 180 days old counts half as much, half-life 180 days). Bots (author type "Bot" or a login matching /\[bot\]$/i) and people without admin, write, or maintain permission are excluded.

### Changes

<!-- docs-sync:changes:start -->
| Docs change | Source |
| --- | --- |
| updated pages/code-with-ai/platforms/mobile.md | [Kilo-Org/cloud#6386](Kilo-Org/cloud#6386) |
| updated pages/ai-providers/openai-chatgpt-plus-pro.md | [Kilo-Org/cloud#6702](Kilo-Org/cloud#6702) |
| updated pages/code-with-ai/platforms/cloud-agent.md | [Kilo-Org/cloud#6683](Kilo-Org/cloud#6683) |
| updated pages/getting-started/byok.md | [Kilo-Org/cloud#6692](Kilo-Org/cloud#6692) |
<!-- docs-sync:changes:end -->

### Pending — will retry

<!-- docs-sync:pending:start -->
_None._
<!-- docs-sync:pending:end -->

### Considered, no docs change needed

<!-- docs-sync:skipped:start -->
| PR | Reason |
| --- | --- |
| [Kilo-Org/cloud#6658](Kilo-Org/cloud#6658) | Internal sandbox lifecycle fix with no user-visible workflow or setting. |
| [Kilo-Org/cloud#6673](Kilo-Org/cloud#6673) | Internal container CA trust plumbing, no user-facing behavior. |
| [Kilo-Org/cloud#6672](Kilo-Org/cloud#6672) | Internal sandbox launch/recovery fix with no documented workflow change. |
| [Kilo-Org/cloud#6660](Kilo-Org/cloud#6660) | Internal cloud-agent queue delivery fix; no new command, setting, or workflow for users. |
| [Kilo-Org/cloud#6226](Kilo-Org/cloud#6226) | Internal gateway alias-routing change, not user-visible. |
| [#14490](#14490) | Tool-call animation and streaming UI polish; users do not need to learn a new workflow. |
| [#14530](#14530) | Bug fix restoring intended worktree-pool behavior, no doc change needed. |
| [#14529](#14529) | Bug fix restoring tab/panel state across project switches. |
| [#14531](#14531) | Reconnect recovery bug fix, restores already-documented behavior. |
| [#14532](#14532) | Bug fix keeping session tab title in sync on rename. |
| [Kilo-Org/cloud#6088](Kilo-Org/cloud#6088) | Removes internal/admin model-experiment surfaces, not public product docs. |
| [Kilo-Org/cloud#6682](Kilo-Org/cloud#6682) | Internal control-socket reconnect race fix, no user-facing change. |
| [#14534](#14534) | Transcript re-render performance bug fix. |
| [#14535](#14535) | Bug fix preserving the loaded browser page across context switches. |
| [Kilo-Org/cloud#6684](Kilo-Org/cloud#6684) | Reverted by Kilo-Org/cloud#6685. |
| [Kilo-Org/cloud#6678](Kilo-Org/cloud#6678) | Dead-code constant removal, no user-visible effect. |
| [Kilo-Org/cloud#6687](Kilo-Org/cloud#6687) | Removes internal model-experiment maintenance and retains tables, no user-facing change. |
| [#14515](#14515) | JetBrains plugin unload crash fix, no documented behavior change. |
| [#14520](#14520) | JetBrains transcript/list rendering performance work. |
| [Kilo-Org/cloud#6614](Kilo-Org/cloud#6614) | Mobile PR Review header and session title bug fix, no doc change needed. |
| [Kilo-Org/cloud#6625](Kilo-Org/cloud#6625) | Internal mobile secure-store error-handling refactor. |
| [Kilo-Org/cloud#6624](Kilo-Org/cloud#6624) | Mobile auth bug fix that stops a retry loop; restores expected sign-in behavior with no new setting or workflow. |
| [#14310](#14310) | Contributor/CI fix making the kilo-v2 checkout installable; not user-visible product behavior. |
| [Kilo-Org/cloud#6611](Kilo-Org/cloud#6611) | Mobile notification-tap fix that selects the session's organization; restores correct behavior rather than adding a learnable feature. |
| [Kilo-Org/cloud#6644](Kilo-Org/cloud#6644) | Mobile sign-in layout/alignment polish; no change to what a user must do. |
| [Kilo-Org/cloud#6601](Kilo-Org/cloud#6601) | Mobile layout fix keeping empty states clear of the tab bar; purely visual. |
| [#14543](#14543) | CI/release infrastructure adding Windows binary code signing; no public docs impact. |
| [Kilo-Org/cloud#6616](Kilo-Org/cloud#6616) | Mobile visual defect fixes and a session-title fallback; no new user workflow or setting. |
| [Kilo-Org/cloud#6630](Kilo-Org/cloud#6630) | Reports an edge-case partial worktree restore; failure-path plumbing with no new user-facing workflow, target setting, or config. |
| [Kilo-Org/cloud#6699](Kilo-Org/cloud#6699) | Cloud Agent e2e stabilization plus internal idle-sandbox capacity handling; not user-visible. |
| [#14545](#14545) | Automated JetBrains release/changelog PR; underlying user-facing changes are triaged from their own PRs. |
| [Kilo-Org/cloud#6708](Kilo-Org/cloud#6708) | Internal AI-gateway request-logging policy change in the admin panel; no existing public docs surface and no change to how users run Kilo Code. |
| [#14533](#14533) | Documentation already shipped with the merged PR. The experimental.task_model_selection flag is gone from the current source, and pages/code-with-ai/agents/model-selection.md, pages/code-with-ai/agents/context-mentions.md, and pages/getting-started/settings/index.md already describe per-task selection as default-on with no stale experiment references. |
| [#14510](#14510) | Documentation already shipped with the merged PR. Marketplace companion-skill support is present in the current source (packages/opencode/src/kilocode/marketplace/companions.ts and installer), and pages/customize/marketplace.md already documents installing, publishing, and removing MCP servers with companion skills. |
<!-- docs-sync:skipped:end -->

---

(bot) Generated by the docs-sync workflow. Humans review and merge; while this PR stays open, the next daily run appends new changes here. Branch: `docs/auto-sync-2026-09-25`.
<!-- docs-sync: processed-through 2026-09-25T07:05:29.302Z -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants