Squashed buildout of the tgcalls testbench:
- CLI test tool with --mode p2p/reflector/group/group-churn,
cross-version interop (--version, --version2), and quiet/summary output
- Linux toolchain + Docker multi-stage build, AWS Fargate mass test harness,
local parallel mass test harness with signaling loss simulation
- SCTP writable gate, retransmission timer tuning, role-based handshake
- InstanceV2CompatImpl (PeerConnection backend with V2Impl signaling) and
SignalingTranslator for v14.0.0 interop
- In-process Go/Pion SFU (ICE+DTLS+SRTP+SCTP per participant) with audio
RTP forwarding, ActiveAudio/VideoSsrcs data channel broadcast, RTCP
feedback path, and CGo c-archive integration
- GroupInstanceReferenceImpl (PeerConnection group-call) and mixed-impl
group mode (--reference-participants), with SDP munging for simulcast
- H264 simulcast group video (FakeVideoTrackSource pattern generator,
FakeVideoSink frame counting, --video flag, two-pass channel setup,
reactive video setup from ActiveVideoSsrcs)
- Group churn stress mode (--mode group-churn, --churn-cycles)
- SFU stream-quality adaptation: BandwidthEstimator, LayerSelector
state machine, RtxRingBuffer, simulcast SSRC rewrite
- Transport-cc feedback generation, NetworkSimulator (delay/jitter/loss/
token-bucket bandwidth), --network-scenario step-down-up
- CLAUDE.md updates throughout
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Delay outgoing messages while the peer in the same (peerId, threadId)
chat is live-typing an incoming message, gated via a new per-account
Postbox `.allTypingDrafts` view feeding a synchronous Set membership
check inside PendingMessageManager.
Postbox:
- Add `AllTypingDraftsView` tracking `Set<PeerAndThreadId>` of active
typing drafts; expose via `PostboxViewKey.allTypingDrafts`.
- Disambiguate `PostboxViewKey` hash arms for `.typingDrafts` (constant
prefix 23) and `.contacts` (16 → 24) to avoid runtime collisions
with peerId-only arms and `.combinedReadState`. Hash values are
runtime-only, so this is safe.
PendingMessageManager:
- Add `.waitingForSendGate(groupId:content:)` parking state for single
messages and albums whose upload finished but are gated on a
typing-draft-clearing event; update `groupId` accessor and
`dataForPendingMessageGroup` so partially-parked albums drain on
gate open.
- Add `.waitingForForwardSendGate` parking state for forwards (no
associated values) so drain section (1) routes single non-grouped
messages via `commitSendingSingleMessage` and section (3) routes
forwards via `sendGroupMessagesContent`, avoiding the double-dispatch
that occurred when forwards reused `.waitingForSendGate`.
- Subscribe to `.allTypingDrafts`; wire the gate at single-message,
album, and forward send paths and at drain.
- Cleanup parked forwards on pending-message removal; snapshot
Dictionary keys before iterating to avoid mutation during iteration.
Specs and plan documents are included under `docs/superpowers/`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Design doc for filling in the empty stub at ListView.swift:2674.
Defines the "strictly scrolled" condition as the equation that the
pin-to-edge scroll math at line 3115 lands on:
apparentFrame.maxY == (visibleSize.height - insets.bottom) + scrollPositioningInsets.bottom
with a 0.5pt tolerance.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>