feat(replay): consolidate interactions and improve app/network evidence - #34
Conversation
Provide a provider-neutral external_event hook with bounded parameter policies and a generic exactly-once network_call token, plus a tugboat_dio interceptor that maps Dio request lifecycles onto that token without importing Dio into core. Co-authored-by: Chinmay Kabi <chinmay@blend.to>
Rename parameter transform field to avoid static/instance clash, append tugboat_dio after auth/retry for Dio FIFO error handling, and cover retries/cache resolves in adapter tests. Also make semantics flags compat tests work on Flutter 3.36+ Tristate APIs. Co-authored-by: Chinmay Kabi <chinmay@blend.to>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e27ca78f4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds provider-neutral “evidence” capture to Tugboat replay sessions so host apps (and adapters like Dio) can record bounded external events and logical network outcomes without coupling the core SDK to specific analytics/HTTP providers.
Changes:
- Introduces core evidence APIs:
TugboatReplay.eventHookfor external events andTugboatReplay.beginNetworkCallfor exactly-once network outcome tokens. - Adds bounded evidence health counters (
TugboatSdkHealth.evidence) and supporting core utilities (parameter snapshotting, route/method normalization, session-bound completion). - Adds new
tugboat_diocompanion package with a Dio interceptor that maps Dio lifecycle callbacks to the core network evidence token; bumps workspace/packages to0.6.0.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pubspec.yaml | Adds packages/tugboat_dio to the workspace and updates Melos test scripts to run both packages. |
| pubspec.lock | Locks new transitive deps introduced by tugboat_dio (e.g., dio). |
| packages/tugboat/test/semantics_flags_compat_test.dart | Updates semantics test to use widget semantics instead of flag construction. |
| packages/tugboat/test/replay/tugboat_health_test.dart | Extends health JSON expectations to include new evidence counters. |
| packages/tugboat/test/external_event_and_network_test.dart | Adds comprehensive tests for external event and network evidence behavior + safety guarantees. |
| packages/tugboat/README.md | Documents new external event and network observation APIs and links to the Dio adapter. |
| packages/tugboat/pubspec.yaml | Bumps tugboat version to 0.6.0. |
| packages/tugboat/lib/tugboat.dart | Exports new evidence/network APIs and TugboatEvidenceHealth. |
| packages/tugboat/lib/src/tugboat.dart | Adds isAcceptingEvidence, eventHook, beginNetworkCall, and fences evidence on deactivate(). |
| packages/tugboat/lib/src/sdk_version.dart | Bumps tugboatSdkVersion constant to 0.6.0. |
| packages/tugboat/lib/src/network_observer.dart | Adds network outcome/failure types + route/method normalization and limits. |
| packages/tugboat/lib/src/health.dart | Adds TugboatEvidenceHealth and wires it into TugboatSdkHealth.toJson(). |
| packages/tugboat/lib/src/external_event.dart | Adds parameter policy types + bounded parameter snapshotting utilities. |
| packages/tugboat/lib/src/evidence_recorder.dart | New session-scoped recorder for external/network evidence, tokens, and counters. |
| packages/tugboat/lib/src/controller.dart | Integrates the evidence recorder into the controller lifecycle and health snapshots. |
| packages/tugboat/example/pubspec.yaml | Updates example to depend on tugboat: ^0.6.0. |
| packages/tugboat/CHANGELOG.md | Adds 0.6.0 release notes describing evidence features and safety guarantees. |
| packages/tugboat_dio/test/tugboat_dio_interceptor_test.dart | Adds Dio adapter tests validating privacy, correctness, lifecycle gating, and ordering behaviors. |
| packages/tugboat_dio/README.md | Documents installation, resolver requirements, ordering, and privacy constraints for the Dio adapter. |
| packages/tugboat_dio/pubspec.yaml | Introduces tugboat_dio package metadata and dependencies (lockstep with tugboat 0.6.0). |
| packages/tugboat_dio/LICENSE | Adds license for the new package. |
| packages/tugboat_dio/lib/tugboat_dio.dart | Exposes the interceptor public API. |
| packages/tugboat_dio/lib/src/tugboat_dio_interceptor.dart | Implements the Dio interceptor and evidence token attachment/cleanup logic. |
| packages/tugboat_dio/CHANGELOG.md | Adds 0.6.0 release notes for the new package. |
| packages/tugboat_dio/analysis_options.yaml | Adds lint configuration for the new package. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- fence external transforms to the admitted capture session - fence Dio route resolution across controller/session replacement - add lifecycle-race regression coverage
…al interactions Claim end-session before sync sink work, unify evidence publish, fence on deactivate without early session_end, and seal parameter snapshot decisions. Also default interactionPublishMode to canonicalOnly with matching docs/tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Host apps can add provider-neutral analytics events and logical API outcomes to Tugboat replay sessions without coupling the core SDK to Amplitude, Firebase, Dio, or another provider. External events use bounded parameter policies, while network evidence records method, a safe route template, final status/outcome, duration, retry count, and a bounded JSON/text response body only for HTTP errors.
The
tugboat_diocompanion package maps Dio's lifecycle onto the generic core token. It emits one final logical outcome after auth/retry handling, never retains successful response bodies, and omits binary or unsupported error bodies. Error bodies are deep-copied and capped at 16 KiB.This update also makes canonical
interactionthe default and improves interaction evidence: pixel churn on animated non-tappable surfaces no longer turns empty-area taps into successful state changes, and delayed interaction settlement preserves the action window active at pointer-down.The packages move in lockstep to
0.6.0. Collector-side enrichment bypass and host-specific rollout remain outside this PR.Why
Design decisions
allowAll; production downgradesallowAllto names-only.>= 400may retain a JSON/text error body. Successful, binary, and unsupported bodies are omitted; retained data is bounded to 16 KiB.Validation
flutter analyze packages/tugboat packages/tugboat_dio— no issuesgit diff --check— passedNew concepts
Session-bound completion tokens
A completion token captures the session identity that existed when asynchronous work started. Completion is accepted only if that same session remains active, preventing a slow request from entering a later replay session.
Error-only response bodies
The equivalent Dio path is automatic. A
2xxresponse never retains its body.