Skip to content

feat(web): undo thread lifecycle actions from toasts - #845

Merged
rynfar merged 19 commits into
pylonfrom
upstream/2026-09-24-thread-undo
Sep 26, 2026
Merged

rynfar merged 19 commits into
pylonfrom
upstream/2026-09-24-thread-undo

Conversation

@rynfar

@rynfar rynfar commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

A successful unpin, settle, snooze, or archive action can now be reversed from Pylon's existing toast. For example, settling a pinned and snoozed thread offers Undo that restores its prior pin order and wake time; the thread shortcut uses that same toast and leaves text-editor undo alone.

The inverse is offered only for an observed state change with a successful command receipt. Duplicate actions share the real pending result; the inverse stays owned until that receipt's event sequence reaches the live shell. Cross-kind actions, deletion, navigation changes, and replacement RPC sessions invalidate stale inverses. Shell events carry an opaque producer-session owner, so a buffered event from an old connection cannot satisfy a new receipt. Bulk snooze transfers each confirmed member's Undo claim without releasing its receipt fence. Every inverse carries its original opaque session owner through the local command queue, checks it against the receiving RPC session, and strips it before the wire request. Pylon's toast UI is retained. The upstream sidebar notice replacement remains a separate product choice.

Validation: After reconciliation with current pylon, 178 focused tests passed; the adversarial review found a settle-Undo race that was fixed and covered by two new tests (34 focused Undo tests pass). Web and client-runtime typechecks, scoped lint, and formatting passed. The final-head CI is green. In an isolated browser with a synthetic thread, settling showed the receipt-backed Undo toast, and clicking Undo restored the thread to the active list.

Browser evidence (synthetic project and thread):

Active thread before settling

Settled thread Undo toast

Implemented by GPT-6 Sol in the Codex harness.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

Deployment failed for project pylon-marketing with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/pylon-code?upgradeToPro=build-rate-limit

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 24, 2026
@github-actions

github-actions Bot commented Sep 24, 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.0 KiB 14.0 KiB −9 B (−0.1%) 15.1 KiB ✅
Codex Thread snapshot wire 7.2 KiB 7.3 KiB +10 B (+0.1%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.7 KiB 6.7 KiB −19 B (−0.3%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 58.0 KiB 58.0 KiB 0 B (0.0%) 66.4 KiB ✅
Codex Live turn messages 9 9 0 (0.0%) 21 ✅
Claude Total thread wire 14.0 KiB 14.0 KiB −6 B (−0.0%) 15.1 KiB ✅
Claude Thread snapshot wire 7.3 KiB 7.3 KiB −2 B (−0.0%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.8 KiB 6.7 KiB −4 B (−0.1%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 58.9 KiB 58.9 KiB 0 B (0.0%) 66.4 KiB ✅
Claude Live turn messages 9 9 0 (0.0%) 21 ✅

Baseline: a6251ae · PR result: a4a0f4e · 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.7 KiB
  • Claude decoded thread snapshot: 116.4 KiB

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

@rynfar

rynfar commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Integration review found a bulk-snooze Undo ownership gap on this head. The silent successful snooze keeps its receipt coalesced until shell projection, but Sidebar's aggregate-toast ThreadUndo.begin clears that result. A same-intent action from another hook before projection can then dispatch a no-op success and offer an inverse. A focused regression reproduces two dispatches where one is expected. I am fixing the aggregate claim transfer on this PR branch and will request independent re-review and exact-head CI. This draft remains on hold; the earlier code-review verdict covered the previous head only.

@rynfar

rynfar commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Landing hold update: review found an additional reconnect race. An Undo inverse queued under session A could bind to replacement session B after the toast click. The owning branch is being updated with an opaque session-owner check at RPC binding, plus a real queued-command A→B regression. This and the bulk-snooze receipt/claim transfer both require fresh independent review and exact-head CI before the draft is ready.

@github-actions github-actions Bot added size:XXL and removed size:XL labels Sep 24, 2026
@rynfar

rynfar commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Independent review PASS on final head ad4f3d85aeb47d33688c689d3174bf88dda9829f.

I checked the bulk snooze claim transfer against the receipt sequence, duplicate and no-op handling, archive navigation identity, cross-kind invalidation, and unpin/settle/snooze inverse chains. All real Undo paths require a live session owner; the optional owner is stripped before wire dispatch, and the RPC request checks it against the exact receiving session. The serial queue regression covers A-owned Undo queued behind another command, then same-ID B replacement before execution: B receives no inverse. Multi-step settle Undo carries the same owner through each command; a reconnect may produce a partial Undo failure but cannot run a stale inverse on B.

This is source and focused-test review. I did not use a browser or device. PR #844 separately adds a complementary pasted-text preflight in the same RPC request function, so combined integration must retain both guards.

@rynfar

rynfar commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

The previous head’s Test failure was confined to seven Undo toast fixtures that created claims without a session owner. The corrected head e088aca9c4 makes owner projection mandatory for real claims, keeps multi-environment aggregate Undo valid only while every confirmed member remains current, and updates those fixtures to use live owner tokens. A null-owner suppression regression is included. Seven directly affected suites pass (86 tests), web typecheck and scoped lint/format pass, and two independent reviewers approved this exact correction. New-head CI is pending; the draft landing hold remains until it completes. The Vercel preview quota failure is tracked separately.

@rynfar

rynfar commented Sep 24, 2026

Copy link
Copy Markdown
Collaborator Author

Independent re-review PASS on e088aca9c407a27376cd7002fb77b67d1b66045e after the Test-job correction.

The seven toast fixtures now create claims with live fake owners, and a new null-owner case confirms no actionable toast. Production ThreadUndo.begin requires a projection/read owner and isCurrent rejects a missing or changed owner; the toast consumes that validity check. The bulk-snooze composite checks every confirmed member, so one expired member or all expired members suppress the batch Undo, while each inverse still carries its own session owner into the RPC guard. This preserves the fail-closed behavior reviewed on the previous head.

…thread-undo

# Conflicts:
#	apps/web/src/components/Sidebar.tsx
#	apps/web/src/keybindings.ts
#	docs/user/keybindings.md
#	packages/client-runtime/src/rpc/client.ts
@vercel

vercel Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
pylon-marketing Ignored Ignored Preview Sep 26, 2026 10:01pm UTC

@rynfar
rynfar marked this pull request as ready for review September 26, 2026 22:38
@rynfar
rynfar merged commit b0c894f into pylon Sep 26, 2026
25 checks passed
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.

1 participant