You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The actionable core work is items 1–3: diagnosis-report ingestion and publication, headless Chat coverage, and the absent native host. Items 4–5 are design questions already overlapping Chat Extension v2 (#487).
Remaining work
1. Diagnosis reports cannot land, for two independent reasons (implementation)
explorer/diagnosis-reports/chat/ holds only ios.md and signing-host-cli.md. There is no chat/android.md, so the chat compatibility matrix has no Android column and nothing has exercised the Kotlin adapter end to end; there is no JS-host report either. ios.md itself is stale: it predates register_bot and reports 5 rows against the worker's 6-method list. #453's body already called this out: "the same shape that let Chat::register_bot sit unimplemented behind a report reading 5 success, 0 failed."
Cause A — ingestion..github/workflows/diagnosis-report.yml extracts the host with
and writes to top-level explorer/diagnosis-reports/$host.md. The chat worker titles its report Truapi Chat Diagnosis, and "Chat" is not in the alternation. The host-qualified ## Truapi iOS Chat Diagnosis fails too, because the lookahead after iOS sees Chat. Both title shapes fail, so no chat report can land through the pipeline; the two committed ones were added by hand in their PRs. The matrix aggregator already handles the chat/ directory and both title shapes, only ingestion is behind.
Cause B — the worker often never publishes the report at all.publishFinalReportIfComplete() has exactly one call site: inside the next handler of chat.listSubscribe() (playground/worker/index.ts:54). The report is therefore posted only if a room-list update happens to arrive after the last probe completes. The last two probes to settle are action_subscribe (driven by an inbound action) and custom_message_render (driven by a host render request) — neither produces a room-list update. A fully green diagnosis can sit unpublished indefinitely.
Observed live: an iOS run completed create_room, list_subscribe, post_message and register_bot, and no report was ever posted. This is host-independent — the CLI battery avoids it only because it never reaches that state.
widen the host regex to accept an optional modality word and route to explorer/diagnosis-reports/<modality>/<host>.md. Fix the write path for SPA reports too: the checked-in tree moved them under spa/ in feat: integrate the Chat modality with the shared Rust core #326 while the workflow still writes top-level $host.md, so fixing only the regex leaves half the bug
call publishFinalReportIfComplete() after handleAction and after a render completes, not only from the room-list subscription
refresh chat/ios.md — note this is not a re-run, see item 3: make ios-chat-run cannot work against develop as it stands
Follow-up coverage, dependent on adoption outside this repo: add chat/android.md once an Android app-side host consumes the #453 surface, and a JS-host report when that path is exercised.
2. Headless coverage: the CLI cannot inject a chat action (implementation)
The CLI worker host (truapi-host signing-host --execution-kind worker; kinds renamed in #459) is the current headless path for Chat, and make e2e-chat-cli exercises it. But the battery drives only create_room and post_message. publish_chat_action appears nowhere under rust/crates/truapi-host-cli/, and the shell has no /chat command, so the CLI cannot drive action_subscribe or custom_message_render. (A JS worker host serves both since #459, but no headless harness uses one.) The other two gaps require no new plumbing: CliChatHost already implements register_chat_bot and subscribe_chat_rooms, they just need battery cases.
Correction to the previous wording. This issue previously said those two methods "rest entirely on the hand-run iOS report from item 1". They do not rest on anything: the committed chat/ios.md predates register_bot, and a live iOS run (item 3) does not reach them either — custom_message_render only fires when the host asks the product to render a stored custom message, which requires the chat screen to be showing it, and action_subscribe produces no host-observable call, so its result is visible only through the final report that cause B suppresses. action_subscribe and custom_message_render have no live end-to-end evidence on any host today.
add register_chat_bot / subscribe_chat_rooms cases to the chat battery
give CliChatHost an action-publisher handle and a /chat post / /chat trigger shell command, then cover the remaining two methods
No CI job runs make e2e-chat-cli: it needs a live host process and a network-backed testnet session, the same reason e2e-signing-cli is not a CI job. The battery only runs when someone runs it.
(#523 keeps the broader scoping question of what the CLI should serve; this is the concrete half.)
3. No native host serves Chat on the shared core, and the iOS harness does not exist on develop (new)
This was missing from the issue and it is the reason Chat "does not work on the rust core" from an app perspective. The core is not at fault.
On polkadot-app-ios-v2@develop:
RustChatExecutionBridge.swift is entirely notImplemented stubs, is never instantiated, and still carries the pre-feat(chat): forward every message variant and add the Android host surface #453 shape (postTextMessage/postCustomMessage, where the current protocol has a single postMessage(roomId:content:)), so it no longer conforms to ChatHostBridge.
openProductExecution is called without the chat: argument, so the core never receives a chat bridge.
ChatRustRuntime's three seams (onUserMessage, renderMessage, dispatchEvent) throw notSupported.
The E2E harness is absent too: neither the three truapi-e2e markers nor any of the TRUAPI_IOS_E2E_* environment hooks the launcher drives (_CHAT_PRODUCT_HOST, _CHAT_MESSAGE, _CHAT_ROOM_ID, _OPEN_CHAT, _PRODUCT_URL, _BROWSE) exist on develop. make ios-chat-run has therefore been non-functional against develop since paritytech/polkadot-app-ios-v2#1310 was closed unmerged — everything it needs lived only on that branch.
Android is in the same position from the other side: the #453 Kotlin surface has no app-side consumer, and the app discards includesChat from the manifest. brevity-dozer (JS) and the CLI host remain the only hosts serving Chat, within the limits of item 2.
A local spike shows the core side is sound. Wiring the bridge and the three seams on top of develop, against a locally built core, produces a working chat path on device: the executor and ws-bridge start, the product connects, and the core drives the native ChatHostBridge through create_room (including New/Exists idempotency), list_subscribe, post_message for both text and custom content, and register_bot — which this host rejects cleanly, since it has no bot registry. That is four of the six V1 methods with live evidence on a native host, the first such coverage. The same run also resolved a published product manifest end to end: root manifest → worker.<name> subname → contenthash → archive → executed worker.
decide who owns reviving the iOS wiring (#1310 is closed; the repo is not ours), and whether the harness hooks land with it
once it lands, produce chat/ios.md through the pipeline against a properly configured app — a report generated on a hand-authored chain list is not publishable evidence
4. Message history / pagination (design, overlaps #487)
Unchanged from #428: a product still has no way to read messages. There is a room-list subscription but no message-history method, so a product only sees actions from the moment it subscribes, plus the 64-item pre-subscribe buffer.
Tracked in the Chat Extension v2 discussion (#487, RFC PR #13). Note that v2 as drafted does not close this gap by itself: registering a message source is opt-in, and in the default path the store stays host-owned with no product-facing read specified.
Since #453 the core forwards every ChatMessageContent variant and leaves unsupported-content rejection to the host. A product therefore cannot determine up front which variants a given host stores or renders. #428 offered narrowing what the protocol advertises as the alternative; forwarding everything resolved that choice, but leaves capability discovery unspecified.
This should probably be settled in #487 alongside the richer Chat surface; contacts are separately covered by RFC PR #17.
Follow-up to #428.
The actionable core work is items 1–3: diagnosis-report ingestion and publication, headless Chat coverage, and the absent native host. Items 4–5 are design questions already overlapping Chat Extension v2 (#487).
Remaining work
1. Diagnosis reports cannot land, for two independent reasons (implementation)
explorer/diagnosis-reports/chat/holds onlyios.mdandsigning-host-cli.md. There is nochat/android.md, so the chat compatibility matrix has no Android column and nothing has exercised the Kotlin adapter end to end; there is no JS-host report either.ios.mditself is stale: it predatesregister_botand reports 5 rows against the worker's 6-method list. #453's body already called this out: "the same shape that letChat::register_botsit unimplemented behind a report reading5 success, 0 failed."Cause A — ingestion.
.github/workflows/diagnosis-report.ymlextracts the host withand writes to top-level
explorer/diagnosis-reports/$host.md. The chat worker titles its reportTruapi Chat Diagnosis, and "Chat" is not in the alternation. The host-qualified## Truapi iOS Chat Diagnosisfails too, because the lookahead afteriOSseesChat. Both title shapes fail, so no chat report can land through the pipeline; the two committed ones were added by hand in their PRs. The matrix aggregator already handles thechat/directory and both title shapes, only ingestion is behind.Cause B — the worker often never publishes the report at all.
publishFinalReportIfComplete()has exactly one call site: inside thenexthandler ofchat.listSubscribe()(playground/worker/index.ts:54). The report is therefore posted only if a room-list update happens to arrive after the last probe completes. The last two probes to settle areaction_subscribe(driven by an inbound action) andcustom_message_render(driven by a host render request) — neither produces a room-list update. A fully green diagnosis can sit unpublished indefinitely.Observed live: an iOS run completed
create_room,list_subscribe,post_messageandregister_bot, and no report was ever posted. This is host-independent — the CLI battery avoids it only because it never reaches that state.explorer/diagnosis-reports/<modality>/<host>.md. Fix the write path for SPA reports too: the checked-in tree moved them underspa/in feat: integrate the Chat modality with the shared Rust core #326 while the workflow still writes top-level$host.md, so fixing only the regex leaves half the bugpublishFinalReportIfComplete()afterhandleActionand after a render completes, not only from the room-list subscriptionchat/ios.md— note this is not a re-run, see item 3:make ios-chat-runcannot work againstdevelopas it standsFollow-up coverage, dependent on adoption outside this repo: add
chat/android.mdonce an Android app-side host consumes the #453 surface, and a JS-host report when that path is exercised.2. Headless coverage: the CLI cannot inject a chat action (implementation)
The CLI worker host (
truapi-host signing-host --execution-kind worker; kinds renamed in #459) is the current headless path for Chat, andmake e2e-chat-cliexercises it. But the battery drives onlycreate_roomandpost_message.publish_chat_actionappears nowhere underrust/crates/truapi-host-cli/, and the shell has no/chatcommand, so the CLI cannot driveaction_subscribeorcustom_message_render. (A JS worker host serves both since #459, but no headless harness uses one.) The other two gaps require no new plumbing:CliChatHostalready implementsregister_chat_botandsubscribe_chat_rooms, they just need battery cases.Correction to the previous wording. This issue previously said those two methods "rest entirely on the hand-run iOS report from item 1". They do not rest on anything: the committed
chat/ios.mdpredatesregister_bot, and a live iOS run (item 3) does not reach them either —custom_message_renderonly fires when the host asks the product to render a stored custom message, which requires the chat screen to be showing it, andaction_subscribeproduces no host-observable call, so its result is visible only through the final report that cause B suppresses.action_subscribeandcustom_message_renderhave no live end-to-end evidence on any host today.register_chat_bot/subscribe_chat_roomscases to the chat batteryCliChatHostan action-publisher handle and a/chat post//chat triggershell command, then cover the remaining two methodsNo CI job runs
make e2e-chat-cli: it needs a live host process and a network-backed testnet session, the same reasone2e-signing-cliis not a CI job. The battery only runs when someone runs it.(#523 keeps the broader scoping question of what the CLI should serve; this is the concrete half.)
3. No native host serves Chat on the shared core, and the iOS harness does not exist on
develop(new)This was missing from the issue and it is the reason Chat "does not work on the rust core" from an app perspective. The core is not at fault.
On
polkadot-app-ios-v2@develop:RustChatExecutionBridge.swiftis entirelynotImplementedstubs, is never instantiated, and still carries the pre-feat(chat): forward every message variant and add the Android host surface #453 shape (postTextMessage/postCustomMessage, where the current protocol has a singlepostMessage(roomId:content:)), so it no longer conforms toChatHostBridge.openProductExecutionis called without thechat:argument, so the core never receives a chat bridge.ChatRustRuntime's three seams (onUserMessage,renderMessage,dispatchEvent) thrownotSupported.truapi-e2emarkers nor any of theTRUAPI_IOS_E2E_*environment hooks the launcher drives (_CHAT_PRODUCT_HOST,_CHAT_MESSAGE,_CHAT_ROOM_ID,_OPEN_CHAT,_PRODUCT_URL,_BROWSE) exist ondevelop.make ios-chat-runhas therefore been non-functional againstdevelopsince paritytech/polkadot-app-ios-v2#1310 was closed unmerged — everything it needs lived only on that branch.Android is in the same position from the other side: the #453 Kotlin surface has no app-side consumer, and the app discards
includesChatfrom the manifest. brevity-dozer (JS) and the CLI host remain the only hosts serving Chat, within the limits of item 2.A local spike shows the core side is sound. Wiring the bridge and the three seams on top of
develop, against a locally built core, produces a working chat path on device: the executor and ws-bridge start, the product connects, and the core drives the nativeChatHostBridgethroughcreate_room(including New/Exists idempotency),list_subscribe,post_messagefor both text and custom content, andregister_bot— which this host rejects cleanly, since it has no bot registry. That is four of the six V1 methods with live evidence on a native host, the first such coverage. The same run also resolved a published product manifest end to end: root manifest →worker.<name>subname → contenthash → archive → executed worker.chat/ios.mdthrough the pipeline against a properly configured app — a report generated on a hand-authored chain list is not publishable evidence4. Message history / pagination (design, overlaps #487)
Unchanged from #428: a product still has no way to read messages. There is a room-list subscription but no message-history method, so a product only sees actions from the moment it subscribes, plus the 64-item pre-subscribe buffer.
Tracked in the Chat Extension v2 discussion (#487, RFC PR #13). Note that v2 as drafted does not close this gap by itself: registering a message source is opt-in, and in the default path the store stays host-owned with no product-facing read specified.
5. Message-content capability discovery (design, overlaps #487)
Since #453 the core forwards every
ChatMessageContentvariant and leaves unsupported-content rejection to the host. A product therefore cannot determine up front which variants a given host stores or renders. #428 offered narrowing what the protocol advertises as the alternative; forwarding everything resolved that choice, but leaves capability discovery unspecified.This should probably be settled in #487 alongside the richer Chat surface; contacts are separately covered by RFC PR #17.