Skip to content

feat: add cross-session messaging - #3778

Open
982945902 wants to merge 5 commits into
apache:mainfrom
982945902:codex/session-mailbox
Open

feat: add cross-session messaging#3778
982945902 wants to merge 5 commits into
apache:mainfrom
982945902:codex/session-mailbox

Conversation

@982945902

@982945902 982945902 commented Aug 25, 2026

Copy link
Copy Markdown

Summary

Add session-level messaging between ordinary root tasks in the same Project.

  • Persist a sender outbox before target admission, reconcile Host receipts/source proof after restart, and settle the sender receipt idempotently without redelivery.
  • Persist typed Runtime Host mailbox provenance and require an exact origin/envelope match before rendering an incoming task card; ordinary user text cannot forge the card.
  • Share the Desktop /send action path through a focused mailbox host, with an immediately searchable task picker, direct return to composition, cancellation, failure feedback, and transcript-settled delivery cards.
  • Add the same searchable picker flow to TUI and keep /rename downstream metadata fresh even when message activity is unchanged.
  • Use semantic surface/border/status/radius tokens for incoming and outgoing mailbox cards.

Scope and WorkHub

This mailbox is deliberately a same-Project primitive. WorkHub keeps its own Workspace/WorkRef resolution and cross-Project transport.

The upstream WorkHub implementation in this tree is a projection/router over ordinary Sessions and does not yet persist a distinct internal orchestration Session role. When that role is introduced, its authority marker must exclude it as a mailbox source/target and suppress mailbox tools at tool-surface composition; this PR does not invent a label that no current Session contract can verify.

Visual evidence

Before sending — the searchable target has been selected and composition stays in the original editor:

Selected target before sending

After sending — the temporary notice is gone and the durable result is a transcript card:

Settled outgoing mailbox card

Verification

Passed:

  • npm run build
  • npm run lint
  • npm run format:check
  • Core: 662/662
  • UI: 230/230
  • Runtime Host mailbox/message coordinator: 46/46
  • Real-provider root tool-surface regression
  • TUI searchable /send keyboard interaction
  • WorkHub rename invalidation regression
  • Desktop Playwright /send: search/deliver, cancel, unavailable-target failure (3/3)
  • git diff --check

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex implemented the feature across Core, Runtime Host, Desktop, TUI, UI rendering, tests, review fixes, and local verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@ARE404 ARE404 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the substantial work here. I reviewed the Runtime Host protocol, model tools, Desktop/TUI flows, transcript projection, tests, and the downstream WorkHub integration boundary.

My recommendation is Request changes because of the two upstream P1 correctness issues below. The WorkHub-specific P1 items are integration blockers for us, but are not necessarily blockers for this upstream PR.

P1 — Must fix before merge

[P1] Sender receipts are not actually durable

In packages/runtime-host/src/server/session-mailbox-coordinator.ts:213-230, the target delivery completes before the sender receipt is persisted. Any failure while reading or appending the receipt is silently swallowed.

This leaves a crash/storage-failure window where the target received the message but the sender permanently lacks the promised durable receipt. The Desktop optimistic projection does not repair persisted state after restart.

Please make receipt persistence recoverable and idempotent—for example, persist an outbox/delivery record before submission and reconcile it, or retain sufficient durable state to repair the sender receipt after delivery.

[P1] Mailbox provenance can be forged with ordinary user text

packages/ui/src/materialize.ts:1087 projects any user message matching the XML-like envelope as an incoming mailbox card. It does not require Host-authored origin or typed mailbox metadata.

An ordinary user message can therefore reproduce the envelope and appear to come from another Session. Strict parsing validates syntax, not provenance.

Please persist a trusted mailbox marker/metadata and require it when projecting mailbox UI. The model-facing envelope can remain textual, but the UI should not infer trusted sender identity from text alone.

P1 — WorkHub integration blockers

These items do not necessarily need to expand the scope of this PR, but WorkHub cannot consume the feature unchanged.

[P1][WorkHub] The internal orchestration Session is exposed as a mailbox participant

isMailboxRoot excludes only subagents and side conversations. WorkHub’s internal Unified Discussion Session would remain a valid source/target and receive the mailbox model tools.

That creates a path for the model to communicate directly with Work Sessions instead of going through the Work Orchestrator.

WorkHub must exclude its internal Session as both source and target and suppress mailbox tools in that Session.

[P1][WorkHub] Mailbox reachability is narrower than WorkHub Workspace scope

sharesWorkspace currently means equal projectId, falling back to equal cwd. WorkHub’s Workspace can contain multiple Projects and identifies targets using a composite WorkRef.

Therefore this transport cannot implement WorkHub’s cross-Project routing directly.

If same-Project messaging is the intended contract of this PR, please describe it consistently as such. WorkHub will retain its own Workspace resolution and cross-Project transport.

P2 — Should fix in this PR

[P2] The TUI /send picker is not searchable

The PR describes an “immediately searchable picker,” but /send calls the generic showSelectPicker at packages/cli/src/pi-tui-runner.ts:3309. That helper provides only arrow/Enter/Esc navigation.

Please add query input/filtering and cover it with a TUI interaction test.

[P2] Mailbox behavior should be extracted from AppShell

Mailbox state, effects, target loading, sending, optimistic receipts, notice projection, and overlay rendering are spread across apps/desktop/src/renderer/app-shell.tsx.

This conflicts with the renderer convention that each app-shell-* module owns one narrow concern. Please extract a mailbox action/host module and consolidate the duplicated target-loading flows.

[P2] The new CSS violates the design token contract

  • chat-message.css:112-114 combines an invented border, surface fill, and --shadow-low on the same boundary.
  • chat-message.css:130 hand-rolls a success wash instead of using --success-wash.
  • composer.css:497 describes card geometry but uses the control-radius tier.

Please use the documented semantic surface, border, elevation, status-wash, and radius tiers.

[P2] UI evidence and interaction coverage are missing

CONTRIBUTING.md requires before/after screenshots or a recording for UI changes.

The changed tests cover Core, Runtime Host, Runtime tools, and UI materialization, but not the actual Desktop/TUI workflows. Please add visual evidence and focused tests for picker search, pending composer state, cancellation, delivery failure, and receipt recovery.

[P2][WorkHub] /rename can leave downstream routing metadata stale

WorkHub currently caches candidate metadata using message activity. Renaming a Session does not necessarily advance that activity marker, so routing UI may retain the old name.

WorkHub needs rename-driven cache invalidation or a metadata revision signal.

P3 — Follow-up cleanup

  • Import SESSION_MAILBOX_TARGET_MAX_ITEMS instead of repeating literal 64.
  • Remove or wire the currently unused delivered and queued composer-notice states.
  • Longer term, store typed mailbox metadata beside the model-facing text instead of serializing and reparsing an ad-hoc envelope.

I did not find unrelated scope creep, and the Runtime Host remains the execution authority. After the upstream P1 issues are fixed, the feature should be usable by WorkHub as a lower-level same-Project messaging primitive, with the WorkHub-specific isolation and routing adaptations listed above.

codex and others added 2 commits August 25, 2026 19:15
@982945902
982945902 force-pushed the codex/session-mailbox branch from db8bc60 to 834505e Compare August 25, 2026 12:12
@982945902

Copy link
Copy Markdown
Author

Addressed the review in 834505ea8 and added visual evidence in 64c284212.

  • Durable sender receipt: the source Session now persists a keyed outbox attempt before target admission. Startup recovery first reconciles the target's durable submit receipt/source proof, writes the missing sender receipt without redelivery, and only retries when no committed target proof exists. A new Host epoch persists a new attempt before retrying. Tests cover append-before-submit ordering, sender append failure, receipt-write failure, restart reconciliation, and no redelivery.
  • Trusted provenance: mailbox delivery now carries a strict typed TurnOrigin.session_mailbox through canonical admission, run storage, recovery, and message persistence. Transcript projection requires an exact typed-origin/envelope match. A forged XML-like ordinary user message remains ordinary text.
  • Searchable TUI flow: /send now opens a query editor plus filtered select list; the keyboard interaction test types a query, selects the target, returns directly to the editor, and sends.
  • Desktop ownership: target loading, picker state, pending composition, sending/failure feedback, optimistic settlement, and picker rendering moved from AppShell into useAppShellMailbox; toolbar and slash-command entry points share the same action.
  • Interaction evidence: Playwright now covers searchable selection + settled transcript card, cancellation without consuming the next message, and an unavailable-target failure that remains actionable. The PR body includes the generated before/after screenshots. Runtime tests cover receipt recovery.
  • Design tokens: cards use the semantic surface, border, status wash, elevation, and radius tiers; unused delivered/queued composer states were removed.
  • WorkHub rename: a regression test verifies rename invalidation and re-read even when activity time is unchanged.
  • Cleanup: imported SESSION_MAILBOX_TARGET_MAX_ITEMS, updated the canonical root tool-surface assertion, and stored typed metadata now rather than leaving it as a follow-up.

The scope wording is now consistently same Project. WorkHub retains its Workspace/WorkRef resolution and cross-Project transport.

For the WorkHub internal orchestration Session: the upstream WorkHub in this tree is currently a projection/router over ordinary Sessions and does not persist such a Session or an authoritative role marker. I did not invent a display label for a security boundary. When that role lands, the same authority marker should be checked by source/target eligibility and root tool-surface composition so the internal Session is excluded on both paths.

Local verification is summarized in the PR body: full build, lint, format, Core 662/662, UI 230/230, mailbox/message coordinator 46/46, provider-wire tool surface, TUI interaction, WorkHub rename regression, and Desktop E2E 3/3.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on 64c2842123:

[P2] Follow-up batch drops mailbox origin leading to raw protocol render

startFollowupBatch only stores execution.origin when batch.sources.length===1. Multiple queued messages from the same mailbox source are aggregated into one UserMessage; origin is then lost for the aggregate. After restart/UI reconstruction the provenance is missing and the trusted parser falls back to raw <session_message> text instead of a card.

Fix: preserve per-source trusted provenance or define safe multi-envelope UI representation; do not render without origin and bypass authenticity boundary.

简体中文聚合后 origin 丢失导致 UI 回退为原文。

@982945902

Copy link
Copy Markdown
Author

Addressed the P2 follow-up provenance issue in 051f6a755.

Trusted Host-authored queue entries now form a hard follow-up boundary: each mailbox message is handed off as its own root, so its persisted UserMessage retains the exact matching execution.origin. Ordinary same-client follow-ups still aggregate as before. This avoids introducing an aggregate origin that could blur the authenticity boundary or misrepresent mixed-source batches.

Added coverage at both layers:

  • message authority: two trusted messages from the same connection cross separate root handoffs;
  • durable execution: two queued mailbox envelopes persist as separate trusted UserMessages and both pass parseTrustedSessionMailboxMessage after re-read.

Validation: 117 related Core/Runtime/UI tests, TUI /send test, desktop mailbox E2E (3/3), full desktop build, lint, and format checks all pass.

@982945902

Copy link
Copy Markdown
Author

Resolved the latest main conflicts in 67f35d115 (merged upstream 2b4c0deaa).

The important integration change is the follow-up provenance fix. Current main now has durable message_admissions and materializes every queue source as its own UserMessage. The mailbox implementation now preserves TurnOrigin.session_mailbox on each admission/source and on each materialized message, while still allowing the Host to hand multiple sources to one successor root. Recovery verifies the stored per-source origin before accepting the handoff. This keeps the authenticity boundary without forcing one root turn per mailbox message.

The metadata schema is now v32 with an idempotent origin_json migration, including compatibility with databases whose version marker and table shape came from different pre-merge branches.

Validation after conflict resolution:

  • Runtime Host, CLI/TUI, UI, and Desktop production builds
  • Runtime Host mailbox/message/root coordination: 103/103
  • TUI/Core/UI surface tests: 182/182
  • SQLite metadata and migration tests: 56/56
  • UI mailbox materialization: 19/19
  • Desktop Electron /send E2E: 3/3
  • repository lint, format check, and diff checks

GitHub now reports the PR as mergeable.

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.

4 participants