Skip to content

🤖 feat: add an experimental native mobile companion - #4103

Draft
ThomasK33 wants to merge 87 commits into
mainfrom
mobile-app-z0ya
Draft

🤖 feat: add an experimental native mobile companion#4103
ThomasK33 wants to merge 87 commits into
mainfrom
mobile-app-z0ya

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Sep 6, 2026

Copy link
Copy Markdown
Member

Summary

Add an experimental, remote-first React Native mobile companion in packages/mobile, built with Expo and isolated from the desktop dependency graph. Execution, Git, terminal, and filesystem tooling remain on an authenticated remote Xum server.

Implementation

  • Stateless HTTP oRPC transport for mobile: every call is a bearer-authenticated request and live updates arrive on exactly two streamed responses per conversation—one shared server.onChanged change stream (config, providers, policy, workspace metadata; new server procedure) and the conversation's workspace.onChat. No socket, ticket, or per-connection state survives a network change; streams heal independently with capped backoff and wake on app foreground, and a dropped conversation resumes from the server's since-cursor with the replayed suffix reconciled atomically instead of replaying the transcript. Native uses expo/fetch for streamed bodies; mutations are never retried. Reverse-proxy path support, native SecureStore credentials, and memory-only browser-preview credentials remain. Mobile connections require HTTPS except for same-device loopback development; private LAN HTTP is rejected before any request. The development preview uses a fixed-target proxy without weakening server Origin checks and ends browser responses when an upstream stream dies.
  • Desktop web token clients keep their WebSocket, exchanging the bearer through HTTP Authorization for short-lived single-use upgrade tickets; socket URLs and subprotocols never carry the long-lived bearer, issuance cannot elevate cookie-only sessions, and ticket-mint 401s clear stale bearer state and retry once without it before requiring authentication.
  • Project/workspace navigation, scratch and repository workspace creation, searchable subagents, native-stack detail screens, session-owned drafts/selections with isolated composer subscriptions, and phone/wide layouts with thumb-reachable composer controls. Delegated workspaces retain their canonical creation identity with locked mode controls; missing-checkout transcripts remain readable without exposing new-work or Git Changes actions. Connected project catalogs refresh on server config changes without restarting the connection. If a selected project disappears, an open creation form preserves its drafts but blocks submission until the project is restored or reselected. Workspace creation also follows live effective runtime policy (local for scratch, worktree for repository checkouts), including client-version blocking, while preserving in-progress drafts. Worktree creation also requires owning-project trust and successful discovery of a local Git branch; unsupported selections direct the user to desktop/server setup without adding mobile trust or Git-init actions.
  • Streaming Markdown, merged reasoning disclosures, shared desktop/native tool-icon semantics, inspectable tool inputs/outputs and flat nested PTC/RLM calls (including legacy replay), display-only filtering of model-only synthetic/workflow rows without changing raw history/cursors, structured question forms with canonical prefilled selections/custom text, interruption, history pagination, and durable partial-answer recovery. Prefills initialize per tool-call identity without overwriting subsequent user edits. Live answers use the existing turn rather than the next-turn model; recovered turns retain current route/policy guards. Text/reasoning display updates are coalesced with immediate control/tool/terminal flushes and a bounded ordered backlog; Markdown parsing remains unchanged. Live queued questions stay disabled until execution starts, and exact durable user-Stop intent excludes stopped partials from question recovery after reconnect without rewriting history.
  • Settings-visible model search, custom model confirmation, inherited agent defaults, thinking controls, live agent/provider/config/policy synchronization, and effective route/auth availability checks. Current selections and drafts survive route or agent-availability loss. Disabled agents block new sends/recovery without rewriting delegated identity; live answers and Stop remain usable. Agent switches preserve the selected model/effort while restoring the target agent’s reasoning preference, including legacy Standard and unconfigured-target fallback behavior.
  • Pinned request context capacity and non-destructive fallback metadata updates across desktop/mobile. Both desktop meters consume the active request pin rather than live provider settings. Active-attempt usage resets on model fallback rather than repricing refused-attempt tokens; transcript parts and session usage remain intact.
  • Queued text, attachment, and review-note restoration into existing drafts. Strict review validation protects live/replay/restore wire projections without discarding original user text. User Stop retires owed monitor attention and disables auto-retry.
  • Focus-scoped RN Web composer shortcuts: fine/wide Enter sends, narrow/coarse Enter remains a newline, idle Cmd/Ctrl+Enter sends, and Escape invokes guarded Stop. Shift+Enter, composition, repeated events, modal focus, and disabled/pending actions are respected; Enter never becomes Stop or queues work during streaming. Native composer keyboard behavior is unchanged. Creation uses context-specific final-field submission while keeping intermediate Next focus transitions.
  • Read-only multi-repository changes through a bulk server API. Header interpretation is confined to each file’s pre-hunk section, preserving header-like source lines and their addition/deletion counts. Native-safe colors are generated from canonical desktop CSS; local Metro startup refreshes the projection, while root/mobile CI reject drift without rewriting it.
  • Make targets, isolated mobile dependencies, focused regression coverage, production browser E2E, documentation, and mobile CI validation.

Validation

  • Targeted backend, workspace-service, desktop, and mobile regression suites; make static-check-full; production RN Web and iOS JS exports.
  • Real HTTP oRPC server fixtures cover bearer transport, streamed subscriptions, abort, timeout, and rejected credentials under both Bun and React Native abort signals; hook tests cover self-healing reconnects, since-cursor resume/downgrade reconciliation, and shared change-stream lifecycle.
  • Disposable authenticated-server E2E and recorded 390px/1200px browser validation cover reconnect, draft/queue recovery, live policy/route changes, structured answers, context/fallback behavior, canonical colors, and tool inspection.
  • Real provider adapters use owned loopback SSE fixtures. Controlled OAuth/gateway snapshots test UI gating without pretending to authenticate to those upstream services.
  • Canonical CSS mutation in a disposable source copy proves direct Expo recoloring and CI no-rewrite drift rejection, followed by restoration of the original palette.
  • The CI Bun coverage crash did not reproduce in the same 94-suite prefix locally: 2,493 passed, three skipped. The matching Goal-seeded sidebar fixture fix subsequently landed upstream and is retained during reconciliation.

Evidence

Screenshots and videos are RN Web evidence, not simulator/device validation.

Regression risks

The mobile client requires a server exposing server.onChanged and the desktop web token client requires ticket issuance; older servers must be updated. Mobile connections to other devices, including private LAN hosts, require trusted HTTPS. Mobile subscriptions are long-lived HTTP responses: intermediaries that buffer or time out idle streams would delay live updates until the client's automatic reconnect. Server-side legacy and cookie-only authentication remain supported. Connection lifetime, cancellation, single-use authorization, replay, and context fallback are covered by focused real-network and UI regressions.

Draft status / limitations

  • Native device/simulator validation remains outstanding. iOS JS export verifies bundling, not a native app build, Keychain, gestures, background/resume, or hardware-keyboard behavior.
  • No native hardware-key command bridge is included. Native multiline composer behavior is preserved; reliable modifier/Escape support would require a native implementation and native validation.
  • This is a remote companion, not an embedded mobile backend. Terminal/VNC, provider administration, and advanced Git editing remain in the main app; mobile Changes is read-only.

Generated with xum • Model: anthropic:claude-fable-5-1 • Thinking: high • Cost: $1723.39

@mintlify

mintlify Bot commented Sep 6, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Mux 🟢 Ready View Preview Sep 6, 2026, 3:34 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@ThomasK33

Copy link
Copy Markdown
Member Author

🤖 Codex-reference navigation and composer polish

Updated in e61d2ecf04aa91935f1c23d0367ff5e23260b505; this PR remains a draft.

  • Phone search/New stay within thumb reach; wide layouts retain top-positioned controls.
  • Conversation headers show project/server context with grouped navigation actions.
  • The input is bottommost, with Plan/model directly above it. It expands for focus/drafts while picker clicks retain browser focus until activation; cancelled drags and keyboard activation behave correctly.
  • Rounded focus indication replaces the browser's inner rectangular outline.

Before / after

Before After
Previous workspace navigation Phone bottom search and create dock
Previous focused composer Corrected bottommost input with controls above
composer-bottom-390.webm

Verification

  • make mobile-check: 68 passing top-level tests, one opt-in integration skipped, 231 assertions; type/lint/format pass.
  • All three browser viewport cases pass (375/390/1200), including control placement, stable pointer-down/click, keyboard activation, search resizing, draft/settings retention and real send/interrupt controls on disposable scratch chats with mock output.
  • Web export, iOS Hermes export and root make static-check pass.
  • Visual checks also cover 375×500; no horizontal overflow, empty-input collapse, first-tap pickers and cancelled pointer drags verified. Final browser diagnostics empty.

The recording is 24.3 seconds. RN Web evidence only: native keyboard/gesture/device validation remains outstanding.


Generated with mux • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $428.45

Implement native connection, grouped workspace navigation, conversation streaming and actions, server-backed creation, model settings, read-only changes, and connection settings. The mobile client uses shared API/types and aborts workspace-bound work on navigation.

Validation: 15 TS/TSX syntax transforms, formatting, seven settings behavior checks. Full mobile typecheck and visual dogfood depend on the parent scaffold and transport integration.
Add a single authenticated, owned WebSocket connection for unary RPC and
subscriptions, with endpoint validation, cancellation, timeout, and no retries.
Reduce real chat events into authoritative, immutable mobile transcript state.

Validate endpoint security, replay/interruption/truncation behavior, and live
oRPC socket authentication, subscription delivery, and mutation lifecycle.
Keep the selected workspace and draft mounted while replacing the closed connection. Abort all prior-connection work, require fresh full replay before chat writes, and cancel late reconnects when disconnecting or unmounting. Warn explicitly before HTTP sends bearer credentials in plaintext.

Validation: five reconnect lifecycle tests (28 assertions), 17 TS/TSX syntax checks, formatting and whitespace. Full RN typecheck and UI evidence remain with parent integration.
Isolate native dependencies and shared schema contracts, add secure credentials and a fixed-target Node preview proxy, and validate transport/replay and connection lifecycle behavior. Document native runtime limits and development commands.

---
_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$12.95`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=12.95 -->
Fix issues found through React Native Web dogfooding: exclude synthetic scratch projects, use the shared model catalog/defaults, persist effective reasoning defaults, and page older history without resurrecting truncated rows. Include behavioral regressions and synchronize the mobile documentation index.

---
_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$36.99`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=36.99 -->
Unify native spacing, type, control/card/sheet radii, and grouped form styling. Keep sheet actions visible, bound web sheets with a dismissible scrim, protect pending workspace creation from dismissal, and require confirmation before disconnecting. Add friendly model search, token visibility, and native keyboard focus progression.

Validation: mobile TypeScript, targeted ESLint, formatting, 60 mobile source tests including five isolated RN-Web form behavior cases. Parent owns integrated desktop/mobile screenshot and recording gates.
Replace manual navigation with a native stack, preserve drafts and selections, and refine conversation, workspace, model, and changes layouts. Add pinned-viewport browser regressions, including composer growth/shrink and navigation retention.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$148.33`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=148.33 -->
Show a neutral fallback when an empty persisted assistant row has no interruption marker; preserve explicit interrupted and active-stream behavior. Cover these branches with native-web behavior tests.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$148.33`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=148.33 -->
Render a calmer native transcript with accessible message roles, hanging Markdown lists, readable literal code blocks, and transparent tool/reasoning action rows. Open bounded tool inspection sheets, retain inline question answers, and derive tool state only from real execution/result metadata.

Validation: mobile TypeScript, targeted ESLint, formatting, 60 mobile source tests including 13 native-web interaction cases. Parent owns integrated reference screenshots and mobile browser verification.
Use quieter native surfaces and lightweight session navigation, center conversation context, integrate model and send controls into one composer, and progressively disclose thinking settings. Preserve transport, draft/model state, and native navigation; add browser coverage for focused settings.

Validated mobile checks, pinned browser viewports, real-server integration, web and iOS Hermes exports, Expo compatibility, and root static checks. Captured reference provenance and real-server UI walkthroughs locally.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$248.65`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=248.65 -->
Use platform-neutral authentication copy in the native app and web development preview. Keep browser-only storage limitations in developer documentation; credential handling is unchanged.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$286.86`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=286.86 -->
Replace the combined conversation settings form with model, mode, and effort picker sheets inspired by the supplied native references. Apply list choices immediately, preserve model/effort when switching mode, and require confirmation only for custom model text.

Verify selection behavior, draft retention, narrow/wide layouts, web and iOS exports, and real-server replay.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$347.29`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=347.29 -->
Show the Settings-visible catalog directly in the native model sheet instead of a four-model provider shortlist. Reuse shared routing, catalog-accessibility and OpenAI auth rules; search provider names, friendly names and aliases without resurrecting removed discovery entries.

Validate hidden and gateway models, cross-provider selection, draft/effort retention, and phone/wide layouts.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$353.19`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=353.19 -->
Bring phone workspace search and creation into a fixed bottom dock, show project/server context in left-aligned conversation headers, and group navigation actions.

Keep the input bottommost with Plan/model controls above it. Expand text entry for focus/drafts while preserving web picker clicks through browser focus retention rather than timers or moving controls below the input. Draw focus on the rounded composer boundary.

Validate phone/wide/short layouts, keyboard and pointer picker activation, draft/settings retention, send/interrupt controls, and native bundling.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$428.45`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=428.45 -->
React Native's abort-controller and Expo's static AbortSignal patch do not provide throwIfAborted, which oRPC invokes before sending the initial authenticated request. Add the missing native compatibility method without replacing existing implementations or bypassing cancellation.

Reproduce the generic connection error with RN's actual abort implementation and a real WebSocket/oRPC server, then run the transport/auth/cancellation suite in an isolated native-global subprocess. Import the package implementation explicitly because Bun aliases its bare name to the host's modern controller.

Validated mobile tests, web/iOS exports, and static checks. Physical-device confirmation remains pending.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$564.47`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=564.47 -->
Use desktop's top-level workspace selector before counting and searching. Share the adjacent-part display projection so persisted stream chunks do not become separate reasoning blocks or paragraphs, without altering authoritative history or tool boundaries.

Show the effective reasoning effort beside the model and a compact context ring using desktop token calculations and the latest step's usage. Context respects compaction/reset boundaries, authoritative completion, replay, and deletion rather than accumulating billing totals.

Verified red/green native-web behavior regressions, live usage/replay/reset tests, mobile checks, production web export, desktop workspace-filter tests, and root static checks. Native keyboard correction follows separately.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$704.34`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=704.34 -->
Use the SDK-pinned keyboard controller for all four native keyboard boundaries, preserving core web behavior and safe-area layout. Measure window offsets rather than guessing header or sheet insets.

Verify the installed overlap algorithm against safe-area and page-sheet geometry, keyboard-height changes, dismissal, and disabled avoidance. Native device positioning still requires iPhone validation.

Validation: make -j1 mobile-check (71 passed, 1 existing integration skip); Expo iOS and web exports; web source maps exclude the native keyboard dependencies.

---

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high -->
Use React Native's cross-platform ARIA aliases because RN Web does not forward accessibilityValue. Add a rendering regression for known, over-limit, and unknown percentages. Keep the browser model-preservation assertion on textContent for both its baseline and comparison now that effort is a separate text node.

Validation: mobile checks, web/iOS exports, and repository static checks pass after these dogfood fixes.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$713.72`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=713.72 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

Mobile parity follow-up

  • Reuse desktop's root-workspace filtering before counts/search, preserving orphan access.
  • Share desktop's adjacent text/reasoning projection so persisted streaming chunks do not become separate accordions or paragraphs. Tool boundaries and authoritative history remain intact.
  • Use Expo SDK 57's keyboard-controller with automatic window offsets across conversation, search, connection, and sheets; preserve the bottommost composer and web focus handling.
  • Show selected effort beside the model and a circular context meter using latest-step usage, provider context limits, and reset/compaction boundaries—not cumulative billing totals.

Validation: mobile checks 73 passed, 1 opt-in integration skip; web/iOS exports; root static checks; desktop workspace-filter tests; browser E2E 3/3 passed at 375, 390, and 1200px. Red/green regressions cover child counts, chunk grouping, usage replay/reset, ARIA progress values, and native keyboard offset calculations.

The browser walkthrough below uses an isolated mock-AI server: one root/five children, raw chunked history, and 200k/1M latest context (20%, distinct from older 60% and cumulative 90%). These are RN Web captures, not physical iPhone keyboard proof. Native keyboard geometry tests use the installed controller with simulated native measurements; the iPhone retry remains necessary. Full-reload unsent state follows the existing in-memory session behavior; Back/reopen retains draft and effort.

Root-only workspace list

Merged transcript, XHIGH effort, and context ring

parity-390.webm

Generated with mux • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $713.72

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66f68541ae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/settings.ts Outdated
Comment thread packages/mobile/App.tsx
Comment thread Makefile
Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/screens/ChangesScreen.tsx Outdated
Comment thread packages/mobile/App.tsx Outdated
Comment thread packages/mobile/src/settings.ts
Comment thread packages/mobile/src/settings.ts Outdated
…in CI

Add one bulk getProjectDiffs operation using validated per-project repo-root execution and fixed git argv with external diff/textconv disabled. Preserve checkout errors and truncation per repository so a clean primary cannot mask secondary changes. Render all results in the mobile changes view.

Run mobile-check after the required workflow's root static checks because mobile's isolated graph is excluded there. Document matching client/server revisions for the evolving API.

Validation: reproduced the old primary-only false-clean UI; mobile checks and root static checks pass; bulk routing/scratch/truncation/error regressions pass; actionlint/zizmor pass. Real disposable two-repository RPC checks also found secondary changes and did not execute the configured external diff helper.

---
_Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$757.08`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=757.08 -->
@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd97460af8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/mobile/src/screens/ChangesScreen.tsx Outdated
Restrict filename lookup and header filtering to each file's pre-hunk section
so source lines beginning with -- or ++ remain visible and counted. Cover
multiple hunks, header suppression, and metadata-only changes in the UI.

---

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$1600.29`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=1600.29 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

🤖 R13 diff-hunk preservation — verified

Source and immutable export: fd0a60cb3.

The Changes view now limits filename/header interpretation to the pre-hunk section. Legitimate deletion/addition payloads beginning --- / +++ remain visible and counted.

Real Git + workspace.getProjectDiffs + production UI verification:

  • Two separate hunks preserve their marker-like source lines; +2/−2 matches git diff --numstat.
  • Deleted path remains deleted.txt, +0/−1.
  • Mode-only metadata remains visible, 100644 → 100755, +0/−0.
  • Actual file headers are hidden; Refresh shows a subsequent real edit without changing counts.
  • No document overflow or browser errors at 390×844 and 1200×900; existing full-app E2Es passed 3/3 at 375/390/1200.

Regression first failed because --- old comment was missing, then passed with the fix. Full mobile checks, static-check, static-check-full, and production web/iOS JavaScript exports passed.

Phone Changes and Refresh

Phone diff retains marker-like hunk lines and exact counts

changes-phone.webm
Wide Changes, deletion and mode-only metadata

Wide diff retains both hunks and metadata-only changes

changes-wide.webm

These are RN Web recordings, not native device/simulator validation. The fixture used the unchanged backend, Node preview, owned loopback providers, and telemetry disabled from launch. All owned services/browsers were stopped and fixture ports released. The PR remains draft.


Generated with xum • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $1603.90

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fd0a60cb37

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/contexts/API.tsx Outdated
Comment thread src/browser/contexts/API.tsx Outdated
Comment thread src/browser/contexts/API.tsx Outdated
Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Keep deleted-checkout transcripts readable without offering a Git action that must fail. Cover disabled navigation, zero diff RPCs, and restoration when the checkout returns.

---

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$1642.49`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=1642.49 -->
Clear persisted and in-memory bearer state on a current ticket-mint 401, then try the ordinary credential-free connection before requiring authentication. Keep retries generation-safe and preserve ticket/cookie security boundaries.

---

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$427.30`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=427.30 -->
Handle Request objects explicitly in ticket-mint fixtures so integrated type-aware lint passes.

---

_Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$1655.69`_

<!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=1655.69 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@ThomasK33

Copy link
Copy Markdown
Member Author

🤖 R14 auth recovery and read-only Changes — verified

Published head: 20cdf9765. Recorded production source: de171a087; the final follow-up only corrects test-fixture URL handling.

Desktop browser authentication

  • Auth-enabled → auth-disabled restart: one ticket 401 → one credential-free WebSocket 101, without reload; stale bearer removed.
  • After offline retry exhaustion, actual Retry reconnects without bearer credentials and with zero new ticket mints.
  • Restart with a different required token: one rejected mint, then the anonymous probe fails and the authentication modal remains stable for over 60 seconds—no fallback loop.
  • Document marker and performance.timeOrigin stay unchanged across recovery and Retry. Restart-unavailable 502s are separately classified, not counted as auth rejections.

Explicit Retry reconnected without a stale bearer

desktop-recovery-retry.webm

A different required token still requires authentication

desktop-required-token-negative.webm

Mobile production RN Web

  • Genuine absent-checkout metadata (transcriptOnly=true) keeps history readable at 375px and 390px.
  • Disabled Changes ignores pointer and focused keyboard activation attempts: zero getProjectDiffs calls and no navigation.
  • A normal checkout retains enabled Changes and displays a real Git diff. Neither phone width has horizontal document overflow.

375px missing-checkout transcript with disabled Changes

390px normal checkout still displays its Git changes

mobile-missing-checkout.webm

Local gates

39 desktop auth/reconnection tests, make mobile-check, make static-check, make static-check-full, and production web/iOS JS exports passed. Test coverage includes late-response credential safety and metadata-driven action restoration. All owned browsers/services were closed; reserved ports are free.

Fixture correction and validation boundaries

The normal-control fixture initially registered an incorrect persisted workspace path, causing its first diff request to fail. Correcting that owned fixture and refreshing produced the real diff shown above; missing-checkout diff requests remained zero throughout. This is browser/RN Web evidence, not physical iOS or simulator validation. Live filesystem-restoration watcher UAT is not claimed.


Generated with xum • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $1658.71

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 20cdf97658

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…port

Every call is its own bearer-authenticated request and every subscription its own
streamed response; no socket, ticket or per-connection state survives a network
change. Streams heal independently with capped backoff and wake on foreground; a
dropped conversation resumes from the server cursor and reconciles the suffix
atomically instead of replaying the transcript. Native uses expo/fetch for streamed
bodies. The desktop web client keeps WebSockets.

---

_Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$1676.39`_

<!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=1676.39 -->
RN Web dogfooding showed six concurrent SSE subscriptions exhausting the browser's
HTTP/1.1 per-host pool, so the unary reads of changed snapshots never completed.
Add `server.onChanged`, one server stream fanning in config, provider, policy and
workspace-metadata changes, shared client-side by every consumer of a client; a
conversation now holds that stream plus its own chat stream. The preview proxy also
ends the browser response when the upstream stream dies so clients see the drop.

---

_Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$1704.94`_

<!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=1704.94 -->
A dropped change stream withdraws the settings and policy snapshots so sending
pauses, but it is not an error: the stream reconnects on its own and the
Reconnecting indicator already explains the pause.

---

_Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$1716.99`_

<!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=1716.99 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

🤖 R15 HTTP transport — verified on RN Web

Published head: 3d401679b. The mobile companion no longer uses WebSockets or upgrade tickets: every call is a bearer-authenticated HTTP request, and live updates arrive on exactly two streamed responses per conversation (server.onChanged + workspace.onChat), one on the workspace list.

Measured transport

  • 0 WebSocket connections, 0 ticket requests; every /orpc request was a POST with Authorization.
  • Open streams: 1 on the list, 2 on a conversation.
  • 12 s backend outage mid-conversation: "Reconnecting…", transcript retained, Send disabled, 0 Retry buttons / no error notice; the drop became observable within ~750 ms.
  • Automatic resume sent onChat with mode: since anchored at row 19 of a 20-row transcript; the replay carried rows 19–21 only (since-replay-proof.json), then a follow-up send succeeded on the same document.
  • Workspace list outage: list stays visible; each reopened change stream re-reads workspace.list once.
  • Server restarted with a different required token: both streams stop after one 401 each, no further requests for 12 s, explicit Retry shows "The server rejected this token."

375px outage: reconnecting indicator, retained transcript, no Retry notice

375px after automatic resume: settings restored and a new send confirmed

transient-outage-no-retry-375.webm

Conversation holds exactly two streams with controls enabled

conversation-recovery-375.webm

A changed required token ends retries with a clear rejection

required-token-negative-390.webm

What the dogfooding caught

The first cut held six SSE subscriptions per conversation, which exhausted Chromium's HTTP/1.1 per-origin pool and silently queued the settings reads (Send stayed disabled). That produced the server.onChanged fan-in stream. The preview proxy also left browser responses open when the upstream stream died; it now ends them so clients see the drop.

Fixture notes

The loopback provider stub answers only scripted prompts; the "Not Found" assistant rows in the recovery recording come from server-side title generation and auto-retry requests hitting that stub, not from the client transport. This is RN Web evidence; native expo/fetch streaming still needs device validation.


Generated with xum • Model: anthropic:claude-fable-5-1 • Thinking: high • Cost: $1723.39

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d401679b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/mobile/scripts/preview.ts
Comment thread packages/mobile/App.tsx Outdated
…ears

The route now follows live workspace metadata: a transcript-only or removed
workspace replaces the diff view instead of refreshing Git into a missing checkout,
and restoring the checkout brings it back in place. A stream wake issued while a
stream was already dying now skips the first backoff instead of being lost.

---

_Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$1725.87`_

<!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=1725.87 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

This comment has been minimized.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant