Skip to content

fix(mobile): restore live tool shimmer and add a Thinking row - #10173

Merged
juliusmarminge merged 2 commits into
mainfrom
t3code/fix-mobile-tool-shimmer-thinking-row
Sep 5, 2026
Merged

juliusmarminge merged 2 commits into
mainfrom
t3code/fix-mobile-tool-shimmer-thinking-row

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 5, 2026 •

Copy link
Copy Markdown
Member

Problem

Two mobile regressions against the web chat view:

  1. The running tool row stopped shimmering. fix(chat): improve tool group summaries and scrolling #9106 narrowed the shimmer from "the trailing live run" to "a call whose lifecycle is still inProgress". Codex only reports inProgress on item.started, which the work log drops, so in practice the mobile summary row lost its shine the moment a call completed while the turn kept going. Web keeps shining until the latest call fails, is declined, or is stopped (fix(chat): keep latest command live between messages #9098, restored again in fix(web): restore the running tool label shine #9777 after the perf pass).
  2. No "Thinking" row. Web shows a shimmering Thinking live activity whenever a turn is working with no shimmering tool row (before the first call, and after a failed one, per fix(chat): replace failed tools with thinking #9165). Mobile never had it, so a working turn with no tools rendered nothing above the composer.

Fix

Mirror web's live-row rules in deriveThreadFeedPresentation:

  • The trailing tool group shimmers while its latest call is running or succeeded. A failed, declined, or stopped call turns the shine off.
  • When a turn is working and no tool row shimmers, append one thinking feed entry. It renders through the existing ShimmeringWorkContent with a brain icon (SF brain, Tabler IconBrain on Android) and uses the same fixed row height as the group toggle, so the list's size estimates stay exact.

The thinking row object is reused across derivations while createdAt/turnId are unchanged, so LegendList keeps the row instance during streaming.

Verification

  • vp test run apps/mobile/src/lib/threadActivity.test.ts — 90 passed. Updated the completed/failed lifecycle expectations to the new rules and added a test for the standalone Thinking row (present while working, stable identity, absent when idle).
  • tsc --noEmit for apps/mobile, targeted vp lint and vp fmt --check on the changed files (only pre-existing warnings in ThreadFeed.tsx).
  • iOS Simulator (iPhone 17 Pro, iOS 26.5) against a disposable base dir seeded with three running turns. Before is main at 62ed748, after is this branch, same dev client, same seeded data.

Working turn, no tool calls yet

Before: nothing above the composer. After: a shimmering Thinking row with a brain icon.

Latest tool call completed, turn still running

The label is identical in both; the difference is motion, so here is the recording (before on the left, after on the right):

https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/3b2347f283343702/pair-completed.mp4

Before and after stills of the Running vp row

Latest tool call failed, turn still running

Before: only the failed row. After: the failed row stays and a Thinking row appears below it.

Android was not exercised (no emulator on the verification host); the only Android-specific change is the Tabler icon mapping.

Implemented by Claude Fable 5 in the Claude Code harness.

Note

Restore live tool shimmer and add a thinking row to mobile thread feed

  • Adds a thinking entry variant to the thread feed type union and renders it as a new ThreadThinkingRow component with a brain icon and shimmering label.
  • The presentation builder appends one thinking row at the tail when a turn is actively working and no work-toggle row is already shimmering; existing thinking rows are filtered out before rebuild to avoid duplicates.
  • A cached thinking entry keeps object identity stable across repeated derivations unless the active-work timestamp or turn id changes.
  • Updates work-group shimmer logic in appendToolGroupRows so a trailing work group shimmers when it has an active activity or when its latest activity succeeded, restoring the live-tool shimmer.
  • Maps the brain SF Symbol to the Tabler brain icon in the Android fallback so ThreadThinkingRow renders correctly on Android.
  • Risk: appendPresentedFeedEntry and appendToolGroupRows in threadActivity.ts now exclude and recompute shimmer for thinking entries; any out-of-tree callers of these helpers will need to handle the new thinking variant.

Macroscope summarized 51cc1ec.

The mobile feed stopped shimmering the running tool row once a call
completed, and never showed the "Thinking" live activity row web has.

Mirror web's live-row rules: the trailing run keeps shining after its
latest call succeeds, only a failed, declined, or stopped call hands
the slot to "Thinking", and a working turn with no live tool row shows
"Thinking" on its own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.6 KiB 13.6 KiB +15 B (+0.1%) 15.1 KiB ✅
Codex Thread snapshot wire 7.0 KiB 7.0 KiB +4 B (+0.1%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.6 KiB 6.6 KiB +11 B (+0.2%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 57.1 KiB 57.1 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 10 10 0 (0.0%) 21 ✅
Claude Total thread wire 13.6 KiB 13.6 KiB +21 B (+0.2%) 15.1 KiB ✅
Claude Thread snapshot wire 7.0 KiB 7.0 KiB −4 B (−0.1%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.5 KiB 6.6 KiB +25 B (+0.4%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 57.8 KiB 57.9 KiB +44 B (+0.1%) 66.4 KiB ✅
Claude Live turn messages 9 10 +1 (+11.1%) 21 ✅

Baseline: 62ed748 · PR result: 51cc1ec · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Sep 5, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 51cc1ec

Macroscope's review found this PR approvable — This is a focused mobile thread-feed bug fix that restores live tool shimmer and adds a small Thinking indicator during active turns. Its impact is confined to presentation logic with targeted state and identity coverage, and it introduces no schema, default, deployment, or sensitive-data changes.

You can add or adjust custom eligibility rules. Learn more.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@macroscopeapp
macroscopeapp Bot dismissed their stale review September 5, 2026 17:52

Dismissing prior approval to re-evaluate 51cc1ec

@juliusmarminge
juliusmarminge merged commit 3fb8942 into main Sep 5, 2026
26 checks passed
@juliusmarminge
juliusmarminge deleted the t3code/fix-mobile-tool-shimmer-thinking-row branch September 5, 2026 22:57
incognitojam added a commit to incognitojam/styal that referenced this pull request Sep 24, 2026
When the PR selected for `early` does not apply at the reconciled
upstream boundary, the command stopped with a single line that gave
nothing to act on:

```console
$ node scripts/upstream-queue.ts early 11784 --through upstream/main
Selected pingdotgg#11784 cannot be applied at the upstream boundary.
```

That happens when the PR builds on upstream work the fork has not taken
in yet, and the planner only looks for dependencies in the changes it
replays after a successful apply.

The command now reports which of the PR's files conflict at the boundary
and which earlier pending upstream PRs and direct commits change those
files, in upstream order. Text output lists the first 20 and says how
many remain; `--json` includes every source with its SHA, PR, and title.
A plan that succeeds prints as before. The intake runbook's `early`
paragraph describes the report.

## Validation

- A new test in `scripts/upstream-early.test.ts` checks which sources
the report lists: pending sources after the boundary and before the
blocked PR whose files overlap the conflicting paths, including direct
commits and directory prefixes, and not recorded or later sources.
- `scripts/upstream-early.test.ts` and `scripts/upstream-queue.test.ts`
pass (21 tests); lint, formatting, and the scripts typecheck are clean.
- Against fetched fork `main` (`495b7cfd5`) and upstream `main`
(`b2b43bef7`), the same command now prints:

  ```console
  $ node scripts/upstream-queue.ts early 11784 --through upstream/main
  Fork 495b7cf; reconciled through d28077e
pingdotgg#11784 does not apply at the reconciled boundary. 16 of its files
conflict there:
    apps/mobile/src/features/threads/ThreadFeed.tsx
    apps/mobile/src/features/threads/thread-work-log.tsx
    apps/mobile/src/lib/threadActivity.ts
    apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
    apps/server/src/orchestration/decider.ts
    apps/server/src/provider/Layers/ClaudeAdapter.test.ts
    apps/server/src/provider/Layers/ClaudeAdapter.ts
    apps/server/src/textGeneration/ThreadTitleContext.test.ts
    apps/server/src/textGeneration/ThreadTitleContext.ts
    apps/server/src/ws.ts
    apps/web/src/components/chat/MessagesTimeline.logic.ts
    apps/web/src/components/chat/MessagesTimeline.tsx
    apps/web/src/components/settings/SettingsPanels.tsx
    packages/client-runtime/src/state/environmentHttpAuth.test.ts
    packages/client-runtime/src/state/threadSnapshotHttp.ts
    packages/contracts/src/orchestration.ts
Earlier pending upstream changes to those files: 110 PRs. Take them in
first, or add their PRs to this plan.
pingdotgg#9594 fix(connect): refresh HTTP credentials without reconnecting
(pingdotgg#9594)
    pingdotgg#9894 fix(chat): show hours for long runs (pingdotgg#9894)
pingdotgg#9933 fix(settings): share restart continuation across environments
(pingdotgg#9933)
    pingdotgg#10092 fix(web): scale agent spawn rows with interface font (pingdotgg#10092)
pingdotgg#9965 fix(web): keep the composer expanded until the thread can scroll
(pingdotgg#9965)
pingdotgg#9935 fix(web): align tool disclosure chevrons with expanded state
(pingdotgg#9935)
pingdotgg#10199 fix(mobile): size a chat image's frame before its bytes arrive
(pingdotgg#10199)
pingdotgg#10200 fix(web): size the chat image slot from server-reported
dimensions (pingdotgg#10200)
pingdotgg#10167 refactor(client-runtime): remove unused runtime exports and
helpers (pingdotgg#10167)
pingdotgg#10173 fix(mobile): restore live tool shimmer and add a Thinking row
(pingdotgg#10173)
pingdotgg#10210 fix(mobile): only make work rows expandable when the body adds
something (pingdotgg#10210)
pingdotgg#10211 fix(mobile): fold subagent lifecycle rows into one batch per
spawn (pingdotgg#10211)
    pingdotgg#10212 fix(mobile): stop clipping expanded tool groups (pingdotgg#10212)
    pingdotgg#9875 feat: show provider usage limits with /usage-limits (pingdotgg#9875)
pingdotgg#9561 fix(ui): unify loading and refresh feedback across clients (pingdotgg#9561)
pingdotgg#10226 refactor(web): keep feature component helpers private (pingdotgg#10226)
pingdotgg#9754 feat(settings): add shared project defaults and scoped overrides
(pingdotgg#9754)
pingdotgg#9895 feat(connections): balance new threads across connected machines
(pingdotgg#9895)
pingdotgg#10273 fix(mobile): stop the work log flickering during subagent runs
and failing calls (pingdotgg#10273)
    pingdotgg#10271 fix(mobile): save linked media from chat (pingdotgg#10271)
    ... 90 more; --json lists every source.
  ```

`--json` returns the same 16 paths and all 110 sources. `early 5521
--through upstream/main`, which plans successfully, prints the same
summary as before.

---
Written by an agent (Claude Code, claude-opus-5-5).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant