Skip to content

feat(replay): consolidate interactions and improve app/network evidence - #34

Merged
Chinmay-KB merged 8 commits into
mainfrom
fix/app-network-observation-audit
Aug 7, 2026
Merged

feat(replay): consolidate interactions and improve app/network evidence#34
Chinmay-KB merged 8 commits into
mainfrom
fix/app-network-observation-audit

Conversation

@Chinmay-KB

@Chinmay-KB Chinmay-KB commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

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_dio companion 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 interaction the 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

  • Product and analytics events need a provider-neutral ingestion path with explicit parameter-value policies.
  • API failures are difficult to diagnose from status codes alone, while successful response bodies add unnecessary volume.
  • Animated/loading surfaces can change pixels independently of a tap and previously caused false successful-interaction classifications.
  • A tap can settle after the next CLI action window opens, which previously attributed the interaction to the wrong action.

Design decisions

  • The app hook records one logical host event before provider fan-out, avoiding provider-specific APIs and duplicate evidence.
  • Parameter values require an allowlist, transform, or exploration-only allowAll; production downgrades allowAll to names-only.
  • Core owns the session-scoped evidence recorder and exactly-once network token. HTTP-client behavior stays in companion packages.
  • Dio is installed after auth/retry interceptors so a recovered request produces one final logical outcome.
  • HTTP status >= 400 may retain a JSON/text error body. Successful, binary, and unsupported bodies are omitted; retained data is bounded to 16 KiB.
  • New recordings emit one canonical interaction. Deprecated legacy-only and dual-write modes remain available temporarily for compatibility.
  • Interaction outcome uses navigation/structural evidence before pixels; ambient animation on a non-tappable target is classified as no visible change.

Validation

  • flutter analyze packages/tugboat packages/tugboat_dio — no issues
  • Focused core SDK and Dio network suites — 39 tests passed
  • Relevant interaction/navigation suites — 24 tests passed
  • CLI compatibility suite for canonical interaction inspection — 317 tests passed
  • git diff --check — passed

New 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.

final call = TugboatReplay.beginNetworkCall(
  method: 'GET',
  route: '/users/:userId',
);

controller.clear();
call.complete(statusCode: 200); // safely dropped as stale

Error-only response bodies

final call = TugboatReplay.beginNetworkCall(
  method: 'POST',
  route: '/projects',
);

call.complete(
  statusCode: 422,
  errorResponseBody: {'code': 'invalid_project'},
);

The equivalent Dio path is automatic. A 2xx response never retains its body.

cursoragent and others added 4 commits August 3, 2026 14:34
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>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/tugboat/lib/src/evidence_recorder.dart
Comment thread packages/tugboat_dio/lib/src/tugboat_dio_interceptor.dart Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.eventHook for external events and TugboatReplay.beginNetworkCall for 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_dio companion package with a Dio interceptor that maps Dio lifecycle callbacks to the core network evidence token; bumps workspace/packages to 0.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.

Comment thread packages/tugboat/lib/src/evidence_recorder.dart
Chinmay-KB and others added 4 commits August 4, 2026 18:47
- 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>
@Chinmay-KB Chinmay-KB changed the title feat(replay): add provider-neutral app and network evidence feat(replay): consolidate interactions and improve app/network evidence Aug 6, 2026
@Chinmay-KB
Chinmay-KB merged commit 0a279a4 into main Aug 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants