Repository navigation
[4.41] Tracking: sync upstream chat@4.31.0 → chat@4.41.1 (0.4.41 wave) #184
Description
Status (2026-10-01)
Wave complete. The work is merged and main is release-prepped as 0.4.41 (UPSTREAM_PARITY = "4.41.1", strict fidelity pin chat@4.41.1 922/922 green). Not yet tagged or published.
Before cutting the release, maintainers need to run these live checks: #262 (Teams SDK 2.1 streaming/edit/delete), #206 (Slack streamed mentions), #208 (stream rotation over 5 min), #215 (agent_view Stop button).
Remaining by choice: #186 (stale branch deletion), #188 (optional contracts), #78 (100 unmapped core tests), #308, #189/#241 (demand-gated).
Why
Upstream vercel/chat is at chat@4.41.1 (2026-09-28, f690af3c). We are at chat@4.31.0 parity (tagged 2026-06-16), shipped as 0.4.31.3 with UPSTREAM_PARITY = "4.31.0". Since then there have been 12 releases (4.32.0 → 4.41.1, including 4.38.1 and 4.41.1) and 254 commits (183 of them touch packages/ source; the rest are docs site, examples and CI). Mapped fidelity files gained about 130 it() cases, and upstream added about 10 new core test files.
The gap is structural. Upstream reworked concurrency (lock heartbeat, per-thread drain isolation), mention semantics (tri-state is_mention), conversation-scoped AI tools, a unified History API, lifecycle events (message updated/deleted, installed/uninstalled, app context, agent sessions) and streaming (placeholder sentinel, Slack native-stream fallback and rotation). It also landed about 30 hardening commits: webhook identity binding, guarded downloads, callback-token replay, tenant-scoped caches and log hygiene. Several of these fix correctness bugs that Slack and Teams streaming users hit today:
- drop-strategy locks expire during long streamed replies;
- Slack native streams die after about 5 minutes;
- incoming Slack code blocks lose their first line;
- Teams rewrites
@inside email addresses as<at>mentions.
This issue tracks the whole wave. Every child issue is written so an agent can pick it up with no other context.
Strategy
One layered jump to 0.4.41, not staged 0.4.35 / 0.4.39 releases:
- Dependencies point the wrong way. The keystone contracts land late upstream: tri-state
is_mention(4.41), conversation context (4.36), History API (4.39) and turn cancellation (4.39). Adapter changes from 4.32 to 4.35 already depend on them, so an honest "0.4.35" would port contracts that 4.41 then changes. - Intermediate states get superseded. Teams mentions moved to the shared scanner in 4.33, and 4.39 then removed the conversion. Telegram MarkdownV2 trimming was reversed.
636da193prunes and renames tests. Staging means porting code and tests we would then delete. - The fidelity pin moves once. The pin can only move to a tag where every mapped test passes. One bump to 4.41.1 gives one authoritative missing-test list, not three rounds.
No separate security patch release. chat-sdk-python has effectively one downstream consumer (chinchill). It pins by git ref, runs single-tenant deployments (so the cross-tenant classes don't apply), and uses Slack and Teams rather than the adapters with the most severe webhook-auth gaps. A 0.4.31.4 would duplicate work that the wave then rewrites. Security fixes ship inside the wave issues and are prioritized first, because most of them have no core blockers (see Start here).
Parity and version flip only at the end. UPSTREAM_PARITY stays "4.31.0" and the version stays 0.4.31.x until #203, which is honest: parity plus extras. Each PR reports its non-strict fidelity count against 4.41.1 in its description (tooling from #185).
Downstream checkpoints (validated by git ref, no release):
- Core checkpoint: after [4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190 through [4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events #202 merge. Run the downstream boundary suite and the Slack live loop against the
mainSHA. The lock heartbeat ([4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190) can be checked earlier, on its own. - Slack + Teams checkpoint: after [4.41/SL1] Slack outbound mentions: code/URL-aware resolution, native-stream path #206–[4.41/SL4] Slack inbound normalization: self-mention decode, content is_mention, mrkdwn fixes, bot author ids, socket retries #209 and [4.41/T1] Teams routing & outbound text: stop <at> rewriting, conversationType in thread ids, per-service-URL clients #216–[4.41/T6] Teams auth: custom token factory precedence, webhook_verifier, sovereign endpoint allowlists #221 merge. Run the Slack live loop (streaming, tool use, markdown, rotation past 5 minutes) and a Teams live loop (mentions, placeholder streaming,
propagate_handler_errors).
Escape hatch: if the wave slips and downstream needs the lock heartbeat or stream rotation sooner, cut 0.4.31.5 from main as a backport release. That follows the existing Python-only patch convention.
Start here
These have no blockers and can run in parallel now, in recommended priority order:
- [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185: fidelity tooling. It unblocks all of core ([4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190, [4.41/C2b] Shared text utilities: bare-mention scanner, code-fence helpers, to_plain_text structural whitespace #193, [4.41/CB] Callback tokens: consume once, bind to conversation, shorter TTL, preserve button fields #194, [4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events #202) and [4.41/SH1] Shared guarded downloader (redirect policy, byte cap, timeout, credential host binding) #204.
- Security items with no blockers:
- [4.41/G1] Google Chat: bind webhook JWT verification to configured identity #222: Google Chat JWT identity binding (the most severe; blocks [4.41/G2] Google Chat: explicit bot identity, media-API downloads, same-space message ids, native pagination #223)
- [4.41/TG0] Telegram: require webhook verification by default, dedupe repeated updates #224: Telegram webhook verification by default
- [4.41/SL0] Slack: installation-scoped caches, drop unresolved installs, strict response_url, bounded regexes #205: Slack installation-scoped caches and unresolved installs (blocks [4.41/SL8] Slack: guarded downloads, Enterprise Grid org-wide installs, egress proxy #213)
- [4.41/TW1] Twilio: isolate locks and channels per conversation, restrict authenticated media downloads #235: Twilio per-conversation locks and channels
- [4.41/L0] Linear: validate comment-thread and agent-session issue ownership #231: Linear issue-ownership checks (blocks [4.41/L1] Linear: stable agent-session thread ids, undetermined mentions for ordinary comments #232)
- [4.41/MS1] Messenger: guard attachment downloads #234: Messenger guarded downloads
- [4.41/LOG1] Stop logging raw webhook bodies / PII across adapters #187: stop logging raw webhook bodies. It is small; land it early and let the adapter PRs rebase.
- Correctness and auth with no blockers: [4.41/T6] Teams auth: custom token factory precedence, webhook_verifier, sovereign endpoint allowlists #221 (Teams auth; the Teams streaming path), [4.41/ST1] Postgres state: reclaim expired set_if_not_exists rows, migration-managed schemas #240 (Postgres
set_if_not_existsexpiry, which [4.41/C1b] Core lifecycle: init retry, dedupe TTL 10min, propagate_handler_errors, webhook dedupe option #191's dedupe relies on), [4.41/W1] WhatsApp: business-scoped user ids (BSUID) and inbound context variants #236 (WhatsApp BSUIDKeyError), [4.41/GH1] GitHub: configurable bot user id #233 (GitHub bot-id self-reply loop). - Hygiene, any time: [4.41/HK1] Housekeeping: prune stale pre-4.31 remote branches #186, [4.41/X1] Shared adapter test contracts (thread-id + self-message) — optional #188 (optional). [4.41/DEF1] Deferred upstream 4.32–4.41 features (demand-gated backlog) #189 is a backlog record, not work.
Once #185 merges, start the Slack/Teams streaming prerequisites right away:
- [4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190 (lock heartbeat), which begins the critical path;
- in parallel, [4.41/C2b] Shared text utilities: bare-mention scanner, code-fence helpers, to_plain_text structural whitespace #193 (which unblocks [4.41/SL1] Slack outbound mentions: code/URL-aware resolution, native-stream path #206), [4.41/CB] Callback tokens: consume once, bind to conversation, shorter TTL, preserve button fields #194, [4.41/SH1] Shared guarded downloader (redirect policy, byte cap, timeout, credential host binding) #204 and [4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events #202.
Critical path
The path to the Slack streaming fixes that matter most downstream:
P0 → C1a (lock heartbeat, max_lock_lifetime_ms) → C1b → C2a → C5 (placeholder sentinel, lightweight threads)
→ SL2 (stream() → None without context, native_streaming + post/edit fallback) → SL3 (rotate native streams before expiry)
P0 → C2b → SL1 (code/URL-aware mentions, resolved stream buffer) ──────────────────────────────────────────→ SL3
- The lock heartbeat lands at step 2 ([4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190), so it is usable by git ref very early.
- Stream rotation ([4.41/SL3] Slack: rotate long native streams before expiry #208) is the end of the chain: six serialized PRs, five of them in core. Keep [4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190, [4.41/C1b] Core lifecycle: init retry, dedupe TTL 10min, propagate_handler_errors, webhook dedupe option #191, [4.41/C2a] Core mentions & message model: tri-state is_mention, mention regex, Author.email/is_system, Message.reply_to #192 and [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199 small and review them promptly, because every day there delays [4.41/SL3] Slack: rotate long native streams before expiry #208.
- The Teams streaming path branches off at [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199: [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199 → [4.41/C6] Thread.reply, Thread.mark_as_read, post_ephemeral options #200 → [4.41/T4] Teams outbound: reactions, targeted ephemeral messages, placeholder-aware native streaming #219 (placeholder-aware native streaming). [4.41/T6] Teams auth: custom token factory precedence, webhook_verifier, sovereign endpoint allowlists #221 and [4.41/T1] Teams routing & outbound text: stop <at> rewriting, conversationType in thread ids, per-service-URL clients #216 (after [4.41/C2a] Core mentions & message model: tri-state is_mention, mention regex, Author.email/is_system, Message.reply_to #192) run alongside.
- [4.41/SL4] Slack inbound normalization: self-mention decode, content is_mention, mrkdwn fixes, bot author ids, socket retries #209 (inbound normalization, the largest consumer-visible change to
message.text) needs [4.41/C2a] Core mentions & message model: tri-state is_mention, mention regex, Author.email/is_system, Message.reply_to #192 and [4.41/C2b] Shared text utilities: bare-mention scanner, code-fence helpers, to_plain_text structural whitespace #193, so it can run in parallel with [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199/[4.41/SL2] Slack streaming: stream() returns None without context, native_streaming config with post+edit fallback #207.
Dependency graph
Arrows point from blocker to blocked. Only hard "Blocked by" edges are shown; soft ordering notes are in each issue.
flowchart LR
subgraph Tooling
P0["P0 fidelity tooling"]
HK1["HK1 prune branches"]
X1["X1 test contracts"]
DEF1["DEF1 deferred backlog"]
C11["C11 pin bump + 0.4.41"]
end
subgraph Core
C1a["C1a lock heartbeat / drains"]
C1b["C1b init retry / dedupe / propagate"]
C2a["C2a tri-state is_mention / Message"]
C2b["C2b mention scanner / code fences"]
CB["CB callback tokens"]
C3["C3 conversation scope / AI tools"]
C4["C4 lifecycle events"]
C5["C5 streaming / thread API"]
C6["C6 reply / mark_as_read"]
C7["C7 turn cancellation"]
C8["C8 History API"]
C9["C9 AI messages"]
C10["C10 cards & modals core"]
LOG1["LOG1 no raw body logs"]
end
subgraph Shared
SH1["SH1 guarded downloader"]
end
subgraph Slack
SL0["SL0 install-scoped caches"]
SL1["SL1 outbound mentions"]
SL2["SL2 stream fallback"]
SL3["SL3 stream rotation"]
SL4["SL4 inbound normalization"]
SL5["SL5 tables / alert attachments"]
SL6["SL6 edit / delete events"]
SL7["SL7 cards & modals"]
SL8["SL8 downloads / Grid / proxy"]
SL9["SL9 agent_view"]
SL10["SL10 agent sessions"]
end
subgraph Teams
T1["T1 routing / outbound text"]
T2["T2 install lifecycle"]
T3["T3 email / secure downloads"]
T4["T4 reactions / ephemeral / streaming"]
T5["T5 cards & dialogs"]
T6["T6 auth / verifier"]
end
subgraph Other
G1["G1 GChat JWT binding"]
G2["G2 GChat identity / media"]
TG0["TG0 TG webhook verification"]
TG1["TG1 TG inbound media"]
TG2["TG2 TG streaming"]
TG3["TG3 TG polling / media groups"]
TG4["TG4 TG replies"]
D1["D1 Discord security"]
D2["D2 Discord features"]
L0["L0 Linear ownership"]
L1["L1 Linear session ids"]
GH1["GH1 GitHub bot id"]
MS1["MS1 Messenger downloads"]
TW1["TW1 Twilio isolation"]
W1["W1 WA BSUID"]
W2["W2 WA templates / errors"]
W3["W3 WA outbound media"]
W4["W4 WA+MS reply / read / downloads"]
ST1["ST1 Postgres expiry"]
GMAIL["GMAIL Gmail adapter"]
end
P0 --> C1a & C2b & CB & C10 & SH1
C1a --> C1b & C3
CB --> C3
C1b --> C2a & TG3
C2a --> C5 & SL4 & T1 & T3 & TG4 & L1
C2b --> SL1 & SL4 & D1 & W4
C3 --> C4 & C8 & D1
C4 --> C7 & SL6 & SL9 & T2
C8 --> C9
C5 --> C6 & C7 & SL2 & T4 & TG2
C6 --> T4 & TG4 & W4 & GMAIL
C7 --> SL10
C10 --> SL7 & T5
C1a & C1b & C2a & C2b & CB & C3 & C4 & C5 & C6 & C7 & C8 & C9 & C10 --> C11
SH1 --> SL8 & T3 & TG1 & W4 & D1
SL0 --> SL8
SL1 --> SL3
SL2 --> SL3
SL4 --> SL5
SL9 --> SL10
T1 --> T2
G1 --> G2
D1 --> D2
L0 --> L1
W1 --> W2 --> W3
Checklist by workstream
-
Shared parse_markdown: multi-backtick code spans, paragraph leading space, quadratic inputs (found in #283) #308 Shared parse_markdown: multi-backtick spans, leading space, quadratic inputs (follow-up from [4.41/SL4b] Slack inbound mrkdwn normalization, channel.post thread ids, Socket Mode retries (remainder of #209) #283)
-
[4.41/HYG] Stop tracking the .coverage data file #304 HYG stop tracking .coverage
-
[4.41/SL4b] Slack inbound mrkdwn normalization, channel.post thread ids, Socket Mode retries (remainder of #209) #283 SL4b Slack inbound normalization remainder (split from [4.41/SL4] Slack inbound normalization: self-mention decode, content is_mention, mrkdwn fixes, bot author ids, socket retries #209)
-
[4.41/TG3b] Telegram outbound media groups: multi-file and multi-attachment sendMediaGroup #278 TG3b Telegram media groups (split from [4.41/TG3] Telegram polling & media: await handlers before advancing offset, media groups, multi-file uploads #227)
-
fix(slack): Enterprise Grid org-wide installs, authorizations[] routing, retry marker (#268) #277 SL8b Enterprise Grid ([4.41/SL8b] Slack: Enterprise Grid org-wide installs, authorizations[] routing, retry marker (split from #213) #268)
-
Teams: support microsoft-teams-apps 2.1 (activity_sender removal, activities update signature) #250 Teams: support microsoft-teams-apps 2.1 (cap lifted to <2.2; live Teams check pending)
Tooling & meta
- [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185 Fidelity tooling: single pin constant, SHA pin, it.each expansion, new core test files
- [4.41/HK1] Housekeeping: prune stale pre-4.31 remote branches #186 Prune stale pre-4.31 remote branches
- [4.41/LOG1] Stop logging raw webhook bodies / PII across adapters #187 Stop logging raw webhook bodies / PII across adapters
- [4.41/X1] Shared adapter test contracts (thread-id + self-message) — optional #188 Shared adapter test contracts (optional)
- [4.41/C11] Bump fidelity pin + UPSTREAM_PARITY to chat@4.41.1, record non-parity rows, cut 0.4.41 #203 Bump fidelity pin +
UPSTREAM_PARITYto chat@4.41.1, record non-parity, cut 0.4.41
Core
- [4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190 Lock heartbeat,
max_lock_lifetime_ms, per-thread drain isolation, debounce drain - [4.41/C1b] Core lifecycle: init retry, dedupe TTL 10min, propagate_handler_errors, webhook dedupe option #191 Init retry, dedupe TTL 10 min,
propagate_handler_errors, webhook dedupe option - [4.41/C2a] Core mentions & message model: tri-state is_mention, mention regex, Author.email/is_system, Message.reply_to #192 Tri-state
is_mention, mention regex,Author.email/is_system,Message.reply_to - [4.41/C2b] Shared text utilities: bare-mention scanner, code-fence helpers, to_plain_text structural whitespace #193 Bare-mention scanner, code-fence helpers,
to_plain_textstructural whitespace - [4.41/CB] Callback tokens: consume once, bind to conversation, shorter TTL, preserve button fields #194 Callback tokens: consume once, conversation-bound, shorter TTL
- [4.41/C3] Conversation context + AI tool scoping (read & write guards, strict_scope) #195 Conversation context + AI tool scoping
- [4.41/C4] Core lifecycle events: message updated/deleted, installed/uninstalled, app context changed #196 Lifecycle events: message updated/deleted, installed/uninstalled, app context
- [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199 Lightweight threads, placeholder sentinel, streaming settings, AG-UI streams
- [4.41/C6] Thread.reply, Thread.mark_as_read, post_ephemeral options #200
Thread.reply,Thread.mark_as_read,post_ephemeraloptions - [4.41/C7] Turn cancellation: abort_turn, thread.signal, typing options, agent-session events #201 Turn cancellation:
abort_turn,thread.signal, typing options, agent-session events - [4.41/C8] Unified History API (bot.history.user/thread/channel), to_prompt_entries, transcripts deprecation #197 Unified History API,
to_prompt_entries, transcripts deprecation - [4.41/C9] AI messages: keep attachment/link-only messages, framework-agnostic tool specs #198 AI messages: attachment/link-only messages, framework-agnostic tool specs
- [4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events #202 Cards & modals core: Chart, Table options, tooltips, Card width, Date/Number inputs
Shared
- [4.41/SH1] Shared guarded downloader (redirect policy, byte cap, timeout, credential host binding) #204 Guarded downloader (redirect policy, byte cap, timeout, credential host binding)
Slack
- [4.41/SL0] Slack: installation-scoped caches, drop unresolved installs, strict response_url, bounded regexes #205 Installation-scoped caches, drop unresolved installs, strict
response_url - [4.41/SL1] Slack outbound mentions: code/URL-aware resolution, native-stream path #206 Outbound mentions: code/URL-aware resolution, native-stream path
- [4.41/SL2] Slack streaming: stream() returns None without context, native_streaming config with post+edit fallback #207
stream()returns None without context;native_streamingwith post+edit fallback - [4.41/SL3] Slack: rotate long native streams before expiry #208 Rotate long native streams before expiry
- [4.41/SL4] Slack inbound normalization: self-mention decode, content is_mention, mrkdwn fixes, bot author ids, socket retries #209 Inbound normalization: self-mention, content
is_mention, mrkdwn, bot authors, socket retries - [4.41/SL5] Slack inbound: pasted tables and alert attachments in message content #210 Pasted tables and alert attachments in message content
- [4.41/SL6] Slack: dispatch message_changed / message_deleted to lifecycle handlers #211 Dispatch
message_changed/message_deletedto lifecycle handlers - [4.41/SL7] Slack cards & modals: data_table / data_visualization blocks, datepicker, number_input, selection change events #212 data_table / data_visualization, datepicker, number_input, selection change events
- [4.41/SL8] Slack: guarded downloads, Enterprise Grid org-wide installs, egress proxy #213 Guarded downloads + egress proxy (Grid split out)
- [4.41/SL8b] Slack: Enterprise Grid org-wide installs, authorizations[] routing, retry marker (split from #213) #268 Enterprise Grid org-wide installs, authorizations[] routing, retry marker (split from [4.41/SL8] Slack: guarded downloads, Enterprise Grid org-wide installs, egress proxy #213)
- [4.41/SL9] Slack agent_view (Agent messaging experience) + declarative agent config #214 agent_view + declarative agent config
- [4.41/SL10] Slack Agent Sessions lifecycle + native stop #215 Agent Sessions lifecycle + native stop
Teams
- [4.41/T1] Teams routing & outbound text: stop <at> rewriting, conversationType in thread ids, per-service-URL clients #216 Stop
<at>rewriting, conversationType in thread ids, per-service-URL clients - [4.41/T2] Teams installation lifecycle + bot join events #217 Installation lifecycle + bot join events
- [4.41/T3] Teams inbound: author email hydration, protected inline attachments, secure downloads #218 Author email hydration, protected inline attachments, secure downloads
- [4.41/T4] Teams outbound: reactions, targeted ephemeral messages, placeholder-aware native streaming #219 Reactions, targeted ephemeral messages, placeholder-aware native streaming
- [4.41/T5] Teams cards & dialogs: Adaptive Card 1.5 Table, tooltips, width, Input.Date/Number #220 Adaptive Card 1.5 Table, tooltips, width, Input.Date/Number
- [4.41/T6] Teams auth: custom token factory precedence, webhook_verifier, sovereign endpoint allowlists #221 Custom token factory precedence,
webhook_verifier, sovereign endpoint allowlists
Google Chat
- [4.41/G1] Google Chat: bind webhook JWT verification to configured identity #222 Bind webhook JWT verification to configured identity
- [4.41/G2] Google Chat: explicit bot identity, media-API downloads, same-space message ids, native pagination #223 Explicit bot identity, media-API downloads, same-space ids, native pagination
Telegram
- [4.41/TG0] Telegram: require webhook verification by default, dedupe repeated updates #224 Require webhook verification by default, dedupe repeated updates
- [4.41/TG1] Telegram inbound: stickers/animations/locations/polls, media identity, mention regex, allowlist, early typing #225 Stickers/animations/locations/polls, media identity, mention regex, allowlist
- [4.41/TG2] Telegram streaming: native draft streaming opt-in, streaming hardening, link-preserving truncation #226 Native draft streaming opt-in, streaming hardening, link-preserving truncation
- [4.41/TG3] Telegram polling & media: await handlers before advancing offset, media groups, multi-file uploads #227 Await handlers before advancing offset, media groups, multi-file uploads
- [4.41/TG4] Telegram replies: replied-to context, reply-to-bot as mention, native replies, portable file data #228 Replied-to context, reply-to-bot as mention, native replies
Discord
- [4.41/D1] Discord correctness & security: thread-parent validation, starter-message routing, mentions/URLs, forwarded snapshots, downloads #229 Thread-parent validation, starter-message routing, mentions/URLs, snapshots, downloads
- [4.41/D2] Discord features: ephemeral slash responses, select values, channel allowlist, global mentions opt-in, rename threads #230 Ephemeral slash responses, select values, channel allowlist, thread rename
Linear & GitHub
- [4.41/L0] Linear: validate comment-thread and agent-session issue ownership #231 Validate comment-thread and agent-session issue ownership
- [4.41/L1] Linear: stable agent-session thread ids, undetermined mentions for ordinary comments #232 Stable agent-session thread ids, undetermined mentions for ordinary comments
- [4.41/GH1] GitHub: configurable bot user id #233 Configurable bot user id
WhatsApp, Messenger, Twilio
- [4.41/TW1] Twilio: isolate locks and channels per conversation, restrict authenticated media downloads #235 Per-conversation locks and channels, restricted authenticated media downloads
- [4.41/MS1] Messenger: guard attachment downloads #234 Messenger: guard attachment downloads
- [4.41/W1] WhatsApp: business-scoped user ids (BSUID) and inbound context variants #236 Business-scoped user ids (BSUID) and inbound context variants
- [4.41/W2] WhatsApp: send_template and typed API errors #237
send_templateand typed API errors - [4.41/W3] WhatsApp: outbound files/media, CTA URL LinkButton, no duplicate card title #238 Outbound files/media, CTA URL LinkButton, no duplicate card title
- [4.41/W4] WhatsApp & Messenger: mark_as_read, native replies, code fences, guarded downloads #239 WhatsApp & Messenger:
mark_as_read, native replies, code fences, guarded downloads
State
- [4.41/ST1] Postgres state: reclaim expired set_if_not_exists rows, migration-managed schemas #240 Postgres: reclaim expired
set_if_not_existsrows, migration-managed schemas
Deferred (demand-gated)
- [4.41/DEF1] Deferred upstream 4.32–4.41 features (demand-gated backlog) #189 Deferred upstream 4.32–4.41 features backlog
- [4.41/GMAIL] Gmail adapter (demand-gated): primitives + Chat adapter #241 Gmail adapter
Release gate for 0.4.41
Must be merged before 0.4.41 is tagged and published:
- Tooling: [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185. [4.41/C11] Bump fidelity pin + UPSTREAM_PARITY to chat@4.41.1, record non-parity rows, cut 0.4.41 #203 merges last: it flips
UPSTREAM_PARITYand the version. It can be opened as soon as core is done, but it waits for this gate. - Core: all of [4.41/C1a] Core concurrency: lock heartbeat, max_lock_lifetime_ms, per-thread drain isolation, debounce drain #190, [4.41/C1b] Core lifecycle: init retry, dedupe TTL 10min, propagate_handler_errors, webhook dedupe option #191, [4.41/C2a] Core mentions & message model: tri-state is_mention, mention regex, Author.email/is_system, Message.reply_to #192, [4.41/C2b] Shared text utilities: bare-mention scanner, code-fence helpers, to_plain_text structural whitespace #193, [4.41/CB] Callback tokens: consume once, bind to conversation, shorter TTL, preserve button fields #194, [4.41/C3] Conversation context + AI tool scoping (read & write guards, strict_scope) #195, [4.41/C4] Core lifecycle events: message updated/deleted, installed/uninstalled, app context changed #196, [4.41/C5] Streaming & thread API: lightweight threads, placeholder sentinel, restore streaming settings, Plan.auto_complete_previous, AG-UI streams #199, [4.41/C6] Thread.reply, Thread.mark_as_read, post_ephemeral options #200, [4.41/C7] Turn cancellation: abort_turn, thread.signal, typing options, agent-session events #201, [4.41/C8] Unified History API (bot.history.user/thread/channel), to_prompt_entries, transcripts deprecation #197, [4.41/C9] AI messages: keep attachment/link-only messages, framework-agnostic tool specs #198, [4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events #202. Strict fidelity at 4.41.1 requires them.
- Shared and security: [4.41/SH1] Shared guarded downloader (redirect policy, byte cap, timeout, credential host binding) #204, [4.41/LOG1] Stop logging raw webhook bodies / PII across adapters #187, [4.41/SL0] Slack: installation-scoped caches, drop unresolved installs, strict response_url, bounded regexes #205, [4.41/G1] Google Chat: bind webhook JWT verification to configured identity #222, [4.41/G2] Google Chat: explicit bot identity, media-API downloads, same-space message ids, native pagination #223, [4.41/TG0] Telegram: require webhook verification by default, dedupe repeated updates #224, [4.41/L0] Linear: validate comment-thread and agent-session issue ownership #231, [4.41/MS1] Messenger: guard attachment downloads #234, [4.41/TW1] Twilio: isolate locks and channels per conversation, restrict authenticated media downloads #235, [4.41/D1] Discord correctness & security: thread-parent validation, starter-message routing, mentions/URLs, forwarded snapshots, downloads #229, [4.41/T3] Teams inbound: author email hydration, protected inline attachments, secure downloads #218.
- Slack: [4.41/SL1] Slack outbound mentions: code/URL-aware resolution, native-stream path #206–[4.41/SL8] Slack: guarded downloads, Enterprise Grid org-wide installs, egress proxy #213.
- Teams: [4.41/T1] Teams routing & outbound text: stop <at> rewriting, conversationType in thread ids, per-service-URL clients #216–[4.41/T6] Teams auth: custom token factory precedence, webhook_verifier, sovereign endpoint allowlists #221.
- Correctness and download hardening: [4.41/TG1] Telegram inbound: stickers/animations/locations/polls, media identity, mention regex, allowlist, early typing #225 (download caps), [4.41/TG3] Telegram polling & media: await handlers before advancing offset, media groups, multi-file uploads #227 (polling message loss), [4.41/W1] WhatsApp: business-scoped user ids (BSUID) and inbound context variants #236 (BSUID crash), [4.41/W4] WhatsApp & Messenger: mark_as_read, native replies, code fences, guarded downloads #239 (WhatsApp credential host binding), [4.41/ST1] Postgres state: reclaim expired set_if_not_exists rows, migration-managed schemas #240, [4.41/GH1] GitHub: configurable bot user id #233.
May trail 0.4.41 as documented non-parity rows in docs/UPSTREAM_SYNC.md (the Linear-deferred precedent from 0.4.30). Each needs a row naming its refs and "tracked in #N":
- [4.41/SL9] Slack agent_view (Agent messaging experience) + declarative agent config #214 and [4.41/SL10] Slack Agent Sessions lifecycle + native stop #215 (Slack agent_view and Agent Sessions)
- [4.41/TG2] Telegram streaming: native draft streaming opt-in, streaming hardening, link-preserving truncation #226, [4.41/TG4] Telegram replies: replied-to context, reply-to-bot as mention, native replies, portable file data #228, [4.41/D2] Discord features: ephemeral slash responses, select values, channel allowlist, global mentions opt-in, rename threads #230, [4.41/L1] Linear: stable agent-session thread ids, undetermined mentions for ordinary comments #232, [4.41/W2] WhatsApp: send_template and typed API errors #237, [4.41/W3] WhatsApp: outbound files/media, CTA URL LinkButton, no duplicate card title #238
- [4.41/X1] Shared adapter test contracts (thread-id + self-message) — optional #188 and [4.41/HK1] Housekeeping: prune stale pre-4.31 remote branches #186 (no code impact)
- [4.41/DEF1] Deferred upstream 4.32–4.41 features (demand-gated backlog) #189 and [4.41/GMAIL] Gmail adapter (demand-gated): primitives + Chat adapter #241: deferred by design, and [4.41/C11] Bump fidelity pin + UPSTREAM_PARITY to chat@4.41.1, record non-parity rows, cut 0.4.41 #203 records them.
Conventions for agents
- One issue = one PR on branch
sync/4.41-<id-lowercase>(e.g.sync/4.41-c1a). Only split when the issue's Metadata says so (e.g. [4.41/SL8] Slack: guarded downloads, Enterprise Grid org-wide installs, egress proxy #213, [4.41/SL10] Slack Agent Sessions lifecycle + native stop #215, [4.41/GMAIL] Gmail adapter (demand-gated): primitives + Chat adapter #241); use-a/-bsuffixes. Keep each PR under about 1.5k LOC. - Put
Closes #Nin the PR body, with a link to this tracking issue. - Respect "Blocked by". Don't start an issue until its blockers are merged to
main. Many core issues touchchat.py,thread.pyandtypes.py, and the blocked-by order is what keeps them from conflicting. Soft-ordering notes ("should land after…") are in each issue's Dependencies section. When you land second, you wire the other issue's hooks, as each issue describes. - Upstream checkout:
git clone https://github.com/vercel/chat.git /tmp/vercel-chat && git -C /tmp/vercel-chat fetch --tags. Read the upstream code at a tag withgit -C /tmp/vercel-chat show chat@4.41.1:<path>, and each commit withgit show <hash>. Don't check out tags in a shared clone. - Before opening the PR:
- Run the full CLAUDE.md validation:
uv run ruff check src/ tests/ scripts/ && uv run ruff format --check src/ tests/ scripts/ && uv run python scripts/audit_test_quality.py && uv run python scripts/verify_test_fidelity.py && uv run pytest tests/ --tb=short -q. - Run strict fidelity at the current pin: clone the pinned tag as CLAUDE.md shows, then run
TS_ROOT=<that clone> uv run python scripts/verify_test_fidelity.py --strict. - After [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185 lands, report the non-strict missing count against 4.41.1 in the PR description.
- Run the full CLAUDE.md validation:
- Apply the
docs/SELF_REVIEW.mdchecks: input sweeps, emit/parse symmetry, unforgeable sentinels, divergence budget and the adversarial-reviewer question. - Port rules (docs/UPSTREAM_SYNC.md):
is not Noneinstead of truthiness for??;- snake_case inside, camelCase at the wire;
hmac.compare_digestfor any secret comparison;- UTC-aware datetimes;
- lazy optional imports;
AsyncMockfor async, and fake clocks instead of sleeps in tests;- no duplicate tests.
- Changelog: add an entry under an "Unreleased (4.41 wave)" heading in
CHANGELOG.md, and call out consumer-visible behavior changes explicitly. Record every divergence or skip indocs/UPSTREAM_SYNC.mdin the same PR. - Security wording: this repo is public. Describe weaknesses at class level and cite the upstream fix and its tests. No exploit steps or payloads in PRs, commits or tests.
- Don't bump
UPSTREAM_PARITY, the fidelity pin or the package version anywhere except [4.41/C11] Bump fidelity pin + UPSTREAM_PARITY to chat@4.41.1, record non-parity rows, cut 0.4.41 #203.
Housekeeping
- Close Port Linear agent sessions (adapter-linear) — deferred from 0.4.30 #151 (Linear agent sessions): shipped in 0.4.31.
- Close Migrate Teams adapter to microsoft-teams-apps (official MS Python SDK) #93 (Teams
microsoft-teams-appsmigration): shipped in 0.4.30. - Close Roadmap: 0.4.26.1 follow-ups (Tier 1 → 3 triage) #63 (0.4.26.1 roadmap): superseded by this issue.
- Pin upstream clone SHA in lint.yml + log it for fidelity reproducibility #79 (pin the upstream SHA) is closed by [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185.
- Extend verify_test_fidelity.py MAPPING to cover all packages/chat/src/*.test.ts #78 (extend the fidelity MAPPING) is advanced by [4.41/P0] Fidelity tooling for the 4.41 wave: single pin constant, SHA pin, it.each expansion, map new core test files #185. It stays open for the remaining unmapped files.
- Discord adapter: port native Gateway WebSocket support (HTTP-only today) #57 (Discord Gateway) stays deferred. Upstream's Gateway changes in this range are discord.js-specific.
- Branch pruning is tracked in [4.41/HK1] Housekeeping: prune stale pre-4.31 remote branches #186.
Activity
patrick-chinchill commentedon Sep 30, 2026
#213 (SL8) is shipping as two PRs, as the issue planned. PR A (guarded downloads + egress proxy) is on
sync/4.41-sl8. The Enterprise Grid half moved to #268 (SL8b,sync/4.41-sl8-grid).fix(slack): code/URL-aware outbound mentions, resolve on native stream (
feat(teams): author email hydration, authenticated inline attachments…
fix(teams): keep outgoing @mentions as text, type group chats in thre…
feat(slack): Agent Sessions lifecycle, native stop and automatic titl…
patrick-chinchill commentedon Oct 1, 2026
#203 is open as draft PR #309. It moves the fidelity pin to
chat@4.41.1(922/922 strict), setsUPSTREAM_PARITY = "4.41.1", bumps the version to 0.4.41 and records the skip/deferred non-parity rows. It does not tag or publish.Every gate issue above is merged on
main. Before tagging and publishing 0.4.41, run these checks against the merge commit:agent_viewStop button ([4.41/SL10] Slack Agent Sessions lifecycle + native stop #215)Note: #206 and #215 are merged (9d59bb8, a78919d) but their issues are still open.
docs(changelog): record 0.4.41 live validation results (#311)
patrick-chinchill commentedon Oct 1, 2026
Released: v0.4.41 (2026-10-01), on PyPI as
chat-sdk==0.4.41. Synced to upstreamchat@4.41.1; strict fidelity 922/922; live-validated on chinchill customer-demo (see the CHANGELOG "Live validation" section). Teams 2.1 and the #215 Agent Sessions Stop were not live-verified (no Teams tenant; opt-in feature unused by consumers).Open follow-ups, tracked separately:
msg_too_longrotation/recoveryparse_markdownedge casesChinchill adoption deltas are recorded on chinchill-api draft PRs #1532 (main) and #1534 (oss/agent-framework). Pin
chat-sdk==0.4.41from PyPI rather than the git SHA; the agent-framework Docker builder has no git.