Skip to content

feat(mobile): keep new-task drafts and queued sends visible - #460

Merged
rynfar merged 29 commits into
pylonfrom
upstream/2026-09-10-mobile-drafts
Sep 11, 2026
Merged

feat(mobile): keep new-task drafts and queued sends visible#460
rynfar merged 29 commits into
pylonfrom
upstream/2026-09-10-mobile-drafts

Conversation

@rynfar

@rynfar rynfar commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

On mobile, unsent work was hard to find and slow to hand off: new-task drafts were invisible outside their composer and limited to one per project, queued messages vanished from the conversation, an in-flight upload blocked Send, and submitting a task left you on the draft sheet through worktree setup. This ports T3 Code's finished mobile drafts and outbox work from the frozen upstream head 6c583620ff7ad3235b135af7107c0543467eecfa, plus the chat-feed, status-pill and thread-row fixes that landed alongside it.

How it was ported

Each source was cherry-picked with -x in upstream order, and every conflict was spliced into Pylon's version of the file. Later sources build on earlier ones, so the history reads as the upstream sequence. Pylon-specific adaptations are described below. Lockfile conflicts took Pylon's pnpm-lock.yaml and regenerated it with vp i; only patch hashes changed.

Sources

Upstream commit PR Outcome Note
c0bf35466c8aa1862572dfa84b51b6fe30fc82d6 #10260 Adopted Drafts and queued tasks share the Unsent slot; labels follow connection and upload state, and Pylon's Held is kept
8e129a0dfb35ac2c03a7320245b5bfb976f5d3bf #10327 Adopted Id-keyed drafts with legacy migration; Pylon's held-send "Start a new thread" now writes a stamped id-keyed draft
95d99373b74edfb3bfd092c61a15999a95727423 #10398 Adopted Feedback banners on web and mobile; Pylon's usage-limits banner placement unchanged
66a24d6c1a008430eebd855cd5640607d5aef38c #10404 Adopted In-flight uploads queue instead of blocking; the Prime follow-up queue still waits
d6aa179ad2afe0424e1410cbafbb119bbd5f7809 #10405 Adopted Outbox icon on existing threads in both list layouts
e1230d6031bc55a21668818d0b585d8887b88579 #10449 Adopted Pending rows in the timeline; Pylon's Manage pending sends row and rollback revert action are kept
5b68b2c8e1e971e4ee6956157a1698646ef52a55 #10435 Adopted Every new task goes through the outbox and opens its thread immediately; held creations get an edit card
7dda0b1c0a95603f1954b81a9fee699be92668f0 #10359 Adopted New thread on branch in both mobile lists
71297974c666b0db50a3e3b1a861742f2cdd4d7d #10479 Adopted LegendList patch; lockfile regenerated
b248f5ad566a8cd3ea2d7d678c1e8aa49c748879 #10484 Adopted Stable pill label measurement; Pylon's animation gating kept
c0d4e95c0d921b5960ad04c7f8abec459ee3c59e #10483 Adopted LegendList patch; lockfile regenerated
e32dd42f8ba0daa2d0c6d6d2e474b7af6b3eb7b4 #10487 Adopted Clean pick; builds on Pylon's #10345 slide-out
b7175371d9f32f3b759a922cdbf727a3214c99a2 #10491 Adopted Clean pick
dc39615aec702ea6d402168f80b4d1613f4f2e0f #10492 Adopted Constant-only conflict
357b8d5217cd62826767b6ce6d7c47915f2777d2 (direct commit) Adopted The v2 label already matched; the legacy Working pill now uses upstream's text-adaptive-sky-600-400 on bg-primary/10
8d7f78121660eb8599d4c5ff40cb4394159abfab #10486 Adopted LegendList patch and its VM test; lockfile regenerated
2c8e95a4b641898322c7312cb67535612606745e #9899 Adopted Shared providerInstanceDisplay in client-runtime; Prime and Antigravity labels come from contracts
3e6f856f2359421958a3aa046f2c393e00f3dc6a #10851 Adopted The rc.112 patch hunk is applied to Pylon's effect@4.0.0-beta.103.patch (same lines)
2a303535305d7d224a750fdee78c66e2a52ab3ab #10496 Adopted Arrange threads screen; Move up and Move down remain

Pylon adaptations

  • Delivery holds. Pylon holds queued sends that fail admission, which upstream does not do. Held pending tasks read Held in both mobile lists and skip the "Sends on reconnect" subtitle and hint. Held timeline rows read Held. A held new-task creation shows the Could not start task card with the hold reason and an Edit task action. That action opens the pending-task editor, which edits or retargets the task; deleting stays in the thread list's long-press menu. Anything typed on the thread screen during setup is merged into the editor after the queued prompt and then cleared from the thread draft, matching the rejected-creation path. Without the card, the new thread screen would show Starting… forever. Once a held creation leaves the outbox (for example, deleted from the iPad sidebar), its card goes away. Held follow-ups do not reserve the floating status pill's space. Held retargets in the new-task editor keep fresh command metadata and remove the superseded entry. The composer's N pending sends on this device · Manage row is kept, because it is the only entry point for Pylon's retry, reconfirm, retarget, new-thread and delete actions. The timeline pencil covers editing only.
  • Provider-bound drafts. ComposerDraftSettingsUpdate keeps providerSelectionExplicit. Editing a pending message from the timeline marks its restored model as explicit, matching Pylon's held-send restore; a focused test pins this. Undoing a draft merge also restores the flag. The held-send Start a new thread action now writes a project-stamped new-task:restored-<messageId> draft and opens it by draftId. The previous project-keyed draft would have been unreachable until the app restarted.
  • Prime follow-up queue. onQueueFollowUp uploads files itself and bypasses the outbox, so it still waits for in-flight uploads. The composer shows "Attachment still uploading" on the follow-up action. Ordinary sends queue as upstream does.
  • Composer copy. The upload-in-flight label follows Pylon's existing "Save pending send" wording, not upstream's "Queue".
  • Direct creation removed. use-project-actions.ts is deleted as upstream deleted it. Pylon's copy differed only by releasing consumed uploads, and the outbox drain already does that.
  • Rollback. The pending-message pencil sits beside Pylon's Revert to this message action, and the pencil now has an Android icon mapping.
  • LegendList patch. Pylon's own scroll-follow deferral (925785841b, pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd) is preserved. It is the only difference from upstream's final patch.
  • Effect. The upgrade to rc.112 is sequenced after this lane, so the Headers getSetCookie fallback is added to Pylon's beta.103 patch (identical line numbers). Without it, reading cookies on a response whose Headers lacks getSetCookie throws, which is what the ported http-response.test.ts exercises.
  • Unsent list performance and labels. The lists read a derived atom over listed new-task drafts that keeps its identity when unrelated drafts change, so typing in a thread composer no longer rebuilds the Home list or iPad sidebar. Queued task labels read Sends on reconnect only while disconnected, Waiting for upload while files still need uploading, and Sending… otherwise.
  • Finished new-task drafts. Clearing a new-task draft on send or Discard deletes the whole entry, so retained mode choices no longer accumulate on disk under unreachable ids.
  • Work-log shimmer. ShimmeringWorkContent accepts upstream's className and textClassName props. Pylon's container keeps its existing class, which has no overflow-hidden.

Nothing Pylon-original was removed. The direct createProjectThread submission path came from upstream and upstream removed it.

Native and release impact

Every change is JavaScript, including the @legendapp/list and effect JS patches. The local @expo/fingerprint source list (iOS, APP_VARIANT=preview, 87 sources) contains none of the changed files. The lockfile only re-keys JavaScript packages that depend on the two patch hashes (@legendapp/list, effect, @effect/*, drizzle-orm, alchemy, @distilled.cloud/*); no native module's resolved path moves. The native fingerprint should therefore be unchanged, and an OTA update is enough, with no new binary. Confirm with the ship-pylon-mobile status script before publishing. The new Android icons (IconUpload, IconMenu2) come from the already bundled @tabler/icons-react-native.

Docs

User docs describe the new mobile thread list (Unsent drafts, held tasks, outbox icon, New thread on branch, account badges), the new-task setup pill and failure card, pending messages in the conversation, sending during uploads on mobile, and Codex feedback notices. Upstream's Arrange threads text was merged into docs/user/thread-sidebar.md.

Verification

  • vp test run in apps/mobile across src/state, src/features/threads, src/features/home, src/features/showcase, src/features/archive and src/lib: 107 files, 1,018 tests passed. New tests cover held-creation draft recovery against the real draft store, draft deletion through a persist and decode round-trip, the listed-drafts atom not notifying on a thread composer edit, delivery labels, and dropping a vanished held creation.
  • vp test run for providerInstanceDisplay.test.ts, threadFeedback.test.ts, orchestrationTiming.test.ts, MessagesTimeline.test.tsx, providerInstances.test.ts, session-logic.test.ts and scripts/legend-list-initial-reveal.test.ts: 7 files, 268 tests passed.
  • Typechecks passed for @t3tools/mobile, @t3tools/web, @t3tools/client-runtime and @t3tools/shared.
  • vp lint and vp fmt --check on every changed source and doc file are clean. knip --exports for web, client-runtime and shared reports nothing.
  • vp run lint:mobile ran, but SwiftLint, ktlint and detekt are not installed on this machine, so no native checks were exercised. No native files changed.
  • vp i regenerated the lockfile after each patch change, and installed packages contain the patched code. PRIME_AGENT_DRIVER_KIND usages are unchanged (3 before and after).
  • No local client pass was run; the orchestrator does one integrated pass later.

Upstream evidence

Screenshots and recordings are in the upstream PRs: #10260, #10327, #10398, #10404, #10405, #10449, #10435, #10359, #10479, #10484, #10483, #10487, #10492, #10486, #9899, #10496.

Tracking: #414.

Ported by Claude Opus 5 in Claude Code.

@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pylon-marketing Ready Ready Preview Sep 11, 2026 1:28am UTC

rynfar added a commit that referenced this pull request Sep 11, 2026
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 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 14.1 KiB 14.1 KiB +4 B (+0.0%) 15.1 KiB
Codex Thread snapshot wire 7.2 KiB 7.2 KiB +5 B (+0.1%) 7.3 KiB
Codex Live turn WebSocket wire 6.9 KiB 6.9 KiB −1 B (−0.0%) 7.8 KiB
Codex Live turn WebSocket decoded 58.8 KiB 58.8 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 10 10 0 (0.0%) 21
Claude Total thread wire 14.1 KiB 14.1 KiB −28 B (−0.2%) 15.1 KiB
Claude Thread snapshot wire 7.2 KiB 7.2 KiB −8 B (−0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.9 KiB 6.9 KiB −20 B (−0.3%) 7.8 KiB
Claude Live turn WebSocket decoded 59.7 KiB 59.7 KiB 0 B (0.0%) 66.4 KiB
Claude Live turn messages 10 10 0 (0.0%) 21

Baseline: 16a9968 · PR result: ccd94cb · 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: 115.6 KiB
  • Claude decoded thread snapshot: 116.3 KiB

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

juliusmarminge and others added 21 commits September 10, 2026 19:25
…ead list (#10260)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit c0bf35466c8aa1862572dfa84b51b6fe30fc82d6)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 8e129a0dfb35ac2c03a7320245b5bfb976f5d3bf)
(cherry picked from commit 95d99373b74edfb3bfd092c61a15999a95727423)
… (#10404)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 66a24d6c1a008430eebd855cd5640607d5aef38c)
…he outbox (#10405)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit d6aa179ad2afe0424e1410cbafbb119bbd5f7809)
(cherry picked from commit e1230d6031bc55a21668818d0b585d8887b88579)
…ed (#10435)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 5b68b2c8e1e971e4ee6956157a1698646ef52a55)
(cherry picked from commit 7dda0b1c0a95603f1954b81a9fee699be92668f0)
(cherry picked from commit 71297974c666b0db50a3e3b1a861742f2cdd4d7d)
(cherry picked from commit b248f5ad566a8cd3ea2d7d678c1e8aa49c748879)
(cherry picked from commit c0d4e95c0d921b5960ad04c7f8abec459ee3c59e)
(cherry picked from commit e32dd42f8ba0daa2d0c6d6d2e474b7af6b3eb7b4)
(cherry picked from commit b7175371d9f32f3b759a922cdbf727a3214c99a2)
(cherry picked from commit dc39615aec702ea6d402168f80b4d1613f4f2e0f)
(cherry picked from commit 8d7f78121660eb8599d4c5ff40cb4394159abfab)
(cherry picked from commit 2c8e95a4b641898322c7312cb67535612606745e)
Co-authored-by: Ryan Hughes <ryan@heyoodle.com>
(cherry picked from commit 3e6f856f2359421958a3aa046f2c393e00f3dc6a)
(cherry picked from commit 2a303535305d7d224a750fdee78c66e2a52ab3ab)
Documents the behavior adopted from the mobile-drafts lane in user docs:
Unsent drafts and held tasks in the mobile thread list, the outbox icon,
New thread on branch, account badges, the new-task setup pill and failure
card, pending messages in the conversation, sending while uploads run on
mobile, and Codex feedback notices.
Pylon marks restored provider picks as explicit so an existing thread's
composer does not re-seed them from thread defaults. Editing a pending
message from the timeline follows the held-send restore path.
Clearing a new-task draft on send or Discard kept its runtime and
interaction modes, so every started or discarded task left a project-less
entry on disk under an id nothing reuses. Clearing a new-task key now
removes the whole entry; thread drafts keep their mode choices as before.
Edit task on a held new task opened the pending-task editor but left
anything typed on the thread screen during setup under a thread id the
server never created. Recovery now seeds the editor draft from the queued
message, merges the thread composer's text and attachments after it,
persists, and clears the thread draft, as a rejected creation already
does. The editor's hydration is shared so both paths fill it identically.

Also corrects the handler comment and user doc: the editor edits or
retargets a held task, and deleting stays in the thread list's menu.
The thread list read the whole composer draft store, which changes on
every keystroke in any composer, so typing a reply rebuilt and re-sorted
the Home list and iPad sidebar. A derived atom now selects only stamped
new-task drafts with content and keeps its previous value when those
entries are unchanged, so unrelated edits no longer notify the lists.

Queued tasks said Sends on reconnect even while connected. The label now
follows this device's view of delivery: Sends on reconnect while
disconnected, Waiting for upload while files still need uploading,
Sending… otherwise, and Pylon's Held for held tasks, in both list
layouts and their accessibility hints.
The Edit pending message button uses the pencil SF Symbol, which had no
Android mapping, leaving a blank tap target.
A held follow-up waits for the user, not delivery, yet it reserved the
floating status pill's space indefinitely, leaving an empty gap above the
composer. Held messages no longer count toward that reservation.

A held creation never delivers or fails on its own, so once it leaves the
outbox (deleted or retargeted, for example from the iPad sidebar) the
thread screen no longer keeps showing its Could not start task card.
Styling follows upstream; the sky meaning for active work is unchanged.

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

Labels

size:XXL 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.

4 participants