Skip to content

feat(truapi): Pocket modality RFC and protocol spec - #609

Open
valentinfernandez1 wants to merge 9 commits into
mainfrom
rfc/pocket-modality
Open

feat(truapi): Pocket modality RFC and protocol spec#609
valentinfernandez1 wants to merge 9 commits into
mainfrom
rfc/pocket-modality

Conversation

@valentinfernandez1

@valentinfernandez1 valentinfernandez1 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Tracking issue: #563

What this defines

Pocket is a collection of product-backed cards owned by the host. A product cannot add a card on its own. The user follows a Pocket deeplink and approves a host dialog that shows the card as it will look. Both the user and the owning product can remove a card. Humanity, Balance and Scarcity are privileged and removable by nobody.

Also defined: the -/pocket/add and -/pocket/open deeplinks, the pocket.cards list in the Worker manifest, and the Widget launch for an expanded card.

Faces are drawn through the Unified Renderer (#633) on its PocketCard context. Worker lifetime is the Worker Lifecycle (#632) reference count, one reference per visible face. Both are cited as merged, so this should merge after them.

Protocol surface

Method Direction Ids
pocket.list_subscribe product to host 206 to 209
pocket.remove_card product to host 210 to 211

Worker execution only. Pocket starts at 206 rather than 198 because the product SDK's host-api package appends its own methods after the last truapi id and holds 198 to 205 downstream. #357 retires flat ids whichever order the two land in.

card_id reuses chat's normalize_chat_identifier and CHAT_FIELD_MAX_BYTES rather than declaring its own bounds. Action ids and payloads belong to the renderer.

Scope

RFC and crate-level spec only. The trait ships with default bodies, so a host with no Pocket surface answers remove_card with Unavailable and ends list_subscribe with an empty Interrupt frame.

Runtime behaviour, the host platform seam, native bindings and the CLI host follow in the "Implementation, rust-core" task of #563.

@valentinfernandez1
valentinfernandez1 requested a review from a team September 4, 2026 16:02
@valentinfernandez1
valentinfernandez1 marked this pull request as draft September 4, 2026 16:02
peetzweg and others added 2 commits September 7, 2026 15:17
The committed Swift bindings gain the Pocket value types and the updated
custom-renderer observer checksum from `make uniffi`.

The playground coverage test enumerated every Worker-pinned service as
"Chat"; Pocket is Worker-pinned too, so it now checks the Chat service by
name.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@valentinfernandez1
valentinfernandez1 marked this pull request as ready for review September 7, 2026 14:28
@valentinfernandez1

Copy link
Copy Markdown
Collaborator Author

@lore-bot-app review

@lore-bot-app

lore-bot-app Bot commented Sep 7, 2026

Copy link
Copy Markdown

Reading the diff and checking what the record says. Back in a few minutes.

@lore-bot-app lore-bot-app 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.

TL;DR
Adds the Pocket RFC, a four-method Pocket trait (wire ids 198 to 211) with stub host defaults, and moves the renderer node types out of chat. 0 blocking, 4 minor. One of the minor items needs a sequencing decision against the open codec-2 wire cutover (#357).

Summary
The PR lands the Pocket modality as a draft RFC plus its protocol surface. truapi gains api/pocket.rs (list_subscribe, remove_card, action_subscribe, host-initiated card_render), v01 payload types, versioned wrappers with encoding tests, and latest re-exports. CustomRendererNode and friends move from v01/chat/custom_renderer.rs to v01/renderer.rs with the wire encoding unchanged. The generated dispatcher and wire table pick up the new service, the schema hash changes, ProductRuntimeHost gets an empty impl Pocket that answers Unavailable and empty streams, and ProductRuntimeControl::render_pocket_card mirrors render_custom_message. iOS bindings are regenerated, the playground chat test is scoped to Chat, and a changeset bumps @parity/truapi and @parity/truapi-host minor. The RFC follows the repo's rfc skill: unnumbered file, _index.md untouched, status: draft, required sections present. The diff contains no instructions addressed to the reviewer.

What the record says

  • Scarcity is the third privileged card. The tracking issue settled that Scarcity joins Humanity and Balance as permanently present and non-removable, layout still open. The RFC matches. #563
  • Pocket was explicitly deferred out of the manifest RFC. The product-manifest RFC discussion marked Pocket as needing a redesign and named the Apple Wallet style "add a card on demand" use case. The deeplink add flow here is the first written answer to that. paritytech/triangle-js-sdks#174
  • Precedent for landing a trait with stub defaults before any host backs it. The Funding RFC did the same: trait plus empty host impl returning unavailable. #339
  • The wire table is mid-redesign. #357 splits the frame discriminant into trait and method bytes and renumbers per trait under codec 2. It is open and was active today. #351 and RFC 0028 (#557, #572) describe the same cutover. This PR allocates flat ids in the table #357 replaces. #357 , #351 , #557
  • Id collisions with downstream extensions have happened before. triangle-js-sdks derives ids from the vendored truapi table and keeps local extension ids in wireTable.extensions.ts; a truapi bump once failed on overlaps. Lore does not index the current extension file, so I cannot confirm 198 to 211 are free there. paritytech/triangle-js-sdks#245 , #350
  • Chat identifier bounds were retrofitted after the modality shipped. #453 and #430 added normalization, screening, and payload caps for chat ids and payloads. Pocket's ids and action payload start without any. #453 , #430
  • The CLI question is still open. #523 asks how to exercise worker-backed Pocket without a host shell and wants the CLI to report served modalities at startup. This PR leaves the CLI answering Unavailable. #523
  • Release 2 tracking lists Pocket manifest declarations as an untracked gap and splits Pocket work into a v2 tracker. #591 , #594
  • Owners per Lore: pgherveou, valentinfernandez1, filvecchiato, johnthecat.

Concerns

  1. Wire ids 198 to 211 are allocated in a table that #357 is about to replace. rust/crates/truapi/src/api/pocket.rs:31,45,66,86 and both wire_table.rs files. Whichever PR merges second has to renumber and regenerate. Not a defect here, but the order should be agreed before merge so one of them does not ship a wire contract that lives for a single release.
  2. render_pocket_card is unreachable from any host. rust/crates/truapi-server/src/host_core.rs:1172. Unlike render_custom_message, it is not exposed in native.rs or wasm.rs, and there is no PocketPlatform seam in truapi-platform the way Chat has ChatPlatform (truapi-platform/src/lib.rs:2771) and Locale has LocaleHost (lib.rs:2728). So impl Pocket for ProductRuntimeHost {} at runtime.rs:2920 cannot be backed by iOS, Android, or a JS host without editing truapi-server. The Funding precedent accepted this shape, so this is a scope statement rather than a bug, but the PR description should say the seam is a follow-up.
  3. No bounds on card_id, action_id, or the action payload. rust/crates/truapi/src/v01/pocket.rs:8,48-53. The RFC calls card_id "a lowercase label" but gives no charset or length, and payload: Option<Vec<u8>> has no cap. Chat got normalize_chat_identifier and a 256 KiB custom payload cap only after hosts diverged (#453). The RFC's Wire surface section is the place to fix these before a second host implements them.
  4. RFC text disagrees with its own snippet on id allocation. docs/rfcs/pocket-modality.md:129 says ids start after "the highest allocated on main at draft time (194)", then uses 198. The highest is 197 (locale_subscribe receive). Small, but it is the spec.

Questions for the author

  1. Does this land before or after #357? If after, will Pocket take a trait byte with methods 0 to 3, and is the flat allocation here throwaway?
  2. Is a PocketPlatform seam plus native and wasm exposure of render_pocket_card the next PR, and is iOS the first consumer given its hard-coded Humanity, Balance, and Scarcity cards?
  3. Should card_id reuse the chat identifier normalization rules, and should the face action payload get an explicit cap in the RFC?
  4. Has anyone checked triangle-js-sdks wireTable.extensions.ts for local ids in 198 to 211?

Next: reply on #357 sequencing, since that decides whether the ids in this PR are final.


🤖 Reviewed by Lore (Parity knowledge base) · 50 agent turns · 446.5s · knowledge as of 2026-09-07

Comment thread rust/crates/truapi/src/api/pocket.rs Outdated
Comment thread rust/crates/truapi-server/src/host_core.rs Outdated
Comment thread rust/crates/truapi/src/v01/pocket.rs Outdated
Comment thread docs/rfcs/pocket-modality.md Outdated
@johnthecat johnthecat mentioned this pull request Sep 8, 2026
5 tasks
valentinfernandez1 and others added 5 commits September 8, 2026 11:49
Resolve the conflicts main's #551 and #617 introduced:

- #551 untracked the generated Rust dispatcher, wire table and iOS Swift
  bindings. Accept the deletions; they are regenerated on demand and the
  Pocket wire entries come back from `scripts/codegen.sh`.
- #617 moved most trait impls out of runtime.rs. Take main's structure and
  re-apply the two Pocket additions on top: `Pocket` in the `truapi::api`
  import, and the stub impl next to `impl Chat`, where main keeps the
  worker-modality impls.
check-rfc.yml holds a newly added RFC to the shape of the template: it
needs `title` and `owner` in the frontmatter, a `## Summary`, a
`## Motivation`, and a design section. The Motivation went missing while
trimming the document, so the gate failed on it.

State the gap the RFC closes: RFC 0024 declares `includes.pocket` and
expects a card, and nothing says which cards a product may back, how one
enters the collection, or who can take it out. Also drop the "what this
RFC adds" self-reference from the summary, which the rfc skill's style
rules cut.
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