* fix(cli): forward async-notifier replies back to originating channel
When PR #214's auto-notifier fires a synthetic agent turn after a
channel-originated conversation, the synthesized response only rendered
to the local CLI/TUI — the channel user (iMessage etc.) saw nothing
and had to manually re-prompt to find out what happened.
Adds a per-thread channel-origin registry in cli/channel.py and wires
the three notifier paths (Rich CLI / TUI / serve) to publish the final
response back via bus.publish_outbound when the originating thread was
started by a channel turn. Publish is fire-and-forget (scheduled on the
bus loop + done-callback for failure logging) so the notifier turn
doesn't block on the asyncio / textual event loop.
The registry is cleared on /new and /resume rotation so stale entries
don't accumulate.
* fix(cli): address review feedback on channel-origin forwarding
Follow-up to the review on #244 (din0s, X-iZhang):
- Guard the /resume origin cleanup on a real thread change in Rich CLI
and TUI (serve mode already did via thread_changed). Resuming the
already-active thread no longer wipes its still-live origin, which
would otherwise silently drop a later async-notifier forward — the
exact gap this PR closes.
- Re-bind the now-current thread to its channel after a channel-issued
/new or /resume slash command (which rotates the thread inside the
dispatch), so notifier turns on the rotated thread still forward.
- Guard the publish done-callback against a cancelled future, whose
.exception() raises CancelledError (rather than returning it) on
bus-loop teardown, so the intended warning still logs.
- Mirror the normal reply path's manager.record_message(channel, "sent")
for forwarded notifications so per-channel stats stay accurate.
- Print the closing "[channel: Replied to ...]" line in all three
notifier paths (Rich CLI / TUI / serve) when a forward actually
happened, so the forwarded block reads as terminated on screen.
Adds test_publish_records_sent_metric. ruff clean; notification-origin
suite (10) + related channel/CLI/serve suites (728) pass.
* fix(cli): store sender information separately from chat_id in channel origin
---------
Co-authored-by: X-iZhang <zacharyzhang2022@gmail.com>