Skip to content

fix(source-amazon-seller-partner): make GET_SALES_AND_TRAFFIC_REPORT_BY_DATE step configurable instead of per-day#77747

Draft
devin-ai-integration[bot] wants to merge 2 commits into
masterfrom
devin/1777927928-amazon-seller-partner-by-date-step
Draft

fix(source-amazon-seller-partner): make GET_SALES_AND_TRAFFIC_REPORT_BY_DATE step configurable instead of per-day#77747
devin-ai-integration[bot] wants to merge 2 commits into
masterfrom
devin/1777927928-amazon-seller-partner-by-date-step

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

What

Resolves https://github.com/airbytehq/oncall/issues/12180:

The GET_SALES_AND_TRAFFIC_REPORT_BY_DATE stream in source-amazon-seller-partner currently issues one Amazon SP-API report request per calendar day because its slice step is hard-coded to P1D. For large backfills this is wasteful (e.g. ~365 separate report requests for a one-year window), and customers have asked us to issue a single (or far smaller number of) request(s) covering a wider window.

The BY_DATE variant of the Sales & Traffic report extracts the salesAndTrafficByDate array, which Amazon's official SP-API report schema already returns broken down per date even for multi-day report windows ("Aggregated data is available at different date range aggregation levels: DAY, WEEK, MONTH. … Requests can span multiple date range periods."). The per-day slicing is therefore unnecessary for this stream.

The sibling GET_SALES_AND_TRAFFIC_REPORT stream (extracting salesAndTrafficByAsin) keeps P1D because Amazon aggregates salesAndTrafficByAsin over the whole gap when dateGranularity: DAY and the range is multi-day — see selling-partner-api-models#426. The GET_SALES_AND_TRAFFIC_REPORT_BY_MONTH stream uses P1M correctly.

How

Single-line manifest change to the BY_DATE stream's incremental_sync, swapping the hard-coded step: "P1D" for the existing period_in_days-driven pattern (capped conservatively at 30 days) used by many other streams in the same manifest:

# The maximum step for this stream is 30 days or lower when the customer configures the period_in_days.
# Amazon's GET_SALES_AND_TRAFFIC_REPORT response already returns salesAndTrafficByDate broken down per
# date for multi-day windows, so a per-day slice is unnecessary and wasteful for large backfills.
step: "P{{ min( config.get('period_in_days', 365), 30 ) }}D"

The period_in_days config field already exists in the spec at manifest.yaml:127 (default 90, minimum 1) — no new config field is added. The 30-day cap is conservative; Amazon does not publish an explicit max date range for this report and a customer hitting the cap simply experiences more (still much smaller than 365) slices, not failures.

Connector version: 5.7.4 → 5.8.0 (minor bump — adds user-visible behavior tied to the existing period_in_days config).

Declarative-First Evaluation

This is a declarative / manifest-only connector (language:manifest-only, cdk:low-code). The fix is purely a YAML change to the existing DatetimeBasedCursor's step expression — it uses the same Jinja min(config.get('period_in_days', …), …) pattern already used by ~10 other streams in the same manifest. No custom Python component is introduced or modified.

Test Coverage

Extended TestSalesAndTrafficReportRequestBody in unit_tests/integration/test_report_based_streams.py with test_by_date_stream_sends_multi_day_window_in_single_request, which asserts that with the default 29-day config range (2023-01-01 → 2023-01-30) the BY_DATE stream issues a single create-report request with dataStartTime/dataEndTime covering the full window — not 29 per-day requests.

I confirmed locally that the new test:

  • Fails without the manifest change (the per-day dataStartTime/dataEndTime does not match the multi-day mocked body).
  • Passes with the manifest change.

All 4 existing tests in TestSalesAndTrafficReportRequestBody continue to pass.

Breaking Change Evaluation

Not a breaking change:

  • Schema / data model: unchanged. The per-record date field continues to come straight from Amazon's salesAndTrafficByDate[].date payload, so widening the slice does not distort per-day record values. Only queryEndDate (a slice-level marker that doubles as the cursor) becomes coarser — same behavior already seen on other period_in_days-driven streams.
  • Spec: no spec field added, removed, or renamed.
  • State: same DatetimeBasedCursor cursor field (queryEndDate) and format.
  • Streams: no streams added or removed.

Review guide

  1. airbyte-integrations/connectors/source-amazon-seller-partner/manifest.yaml — the actual one-line behavior change (plus a clarifying comment).
  2. airbyte-integrations/connectors/source-amazon-seller-partner/unit_tests/integration/test_report_based_streams.py — new test verifying single multi-day request.
  3. airbyte-integrations/connectors/source-amazon-seller-partner/metadata.yaml and docs/integrations/sources/amazon-seller-partner.md — version bump + changelog entry.

User Impact

Customers running the BY_DATE stream over large date ranges will see a substantial reduction in SP-API report requests (e.g. ~365 → ~12 requests for a one-year backfill, with the default 30-day cap). Sync time should drop accordingly. No change to record-level data: date continues to come straight from Amazon's response, and existing customers can still opt for smaller windows by lowering period_in_days.

Coordination

cc Teo (@tgonzalezc5) (Aldo Gonzalez), original author of the BY_DATE stream in #72258 — would appreciate a sanity check, since this changes the slicing behavior the original PR introduced.

Can this PR be safely reverted and rolled back?

  • YES 💚
  • NO ❌

Link to Devin session: https://app.devin.ai/sessions/535847d8b01c4b1ebcd3ca8524eb064d

…BY_DATE step configurable instead of per-day

The BY_DATE variant of the Sales and Traffic report extracts the
`salesAndTrafficByDate` array, which Amazon already returns broken down
per date even for multi-day report windows. Hard-coding `step: P1D` on
this stream caused one SP-API report request per calendar day, which is
unnecessary and wasteful for large backfills.

Switch to the same `period_in_days`-driven step pattern used by other
streams in the same manifest (capped at 30 days).

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: bot_apk <apk@cognition.ai>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
      • Bump types: patch (default), minor, major, major_rc, rc, promote.
      • The rc type is a smart default: applies minor_rc if stable, or bumps the RC number if already RC.
      • The promote type strips the RC suffix to finalize a release.
      • Example: /bump-version type=rc or /bump-version type=minor
    • /bump-progressive-rollout-version - Alias for /bump-version type=rc. Bumps with an RC suffix and enables progressive rollout.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 📝 AI Documentation:
    • /ai-docs-review - AI-powered documentation review for PRs with connector changes.
    • /ai-create-docs-pr - Creates a documentation PR for connector changes, stacked on the current PR.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Deploy preview for airbyte-docs ready!

Project:airbyte-docs
Status: ✅  Deploy successful!
Preview URL:https://airbyte-docs-2xyg7cd88-airbyte-growth.vercel.app
Latest Commit:1c5a7a5

Deployed with vercel-action

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

source-amazon-seller-partner Connector Test Results

507 tests   504 ✅  19m 22s ⏱️
  2 suites    3 💤
  2 files      0 ❌

Results for commit 1c5a7a5.

♻️ This comment has been updated with latest results.

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

↪️ Triggering /ai-prove-fix per Hands-Free AI Triage Project triage next step.

Reason: Draft PR linked to P3 oncall issue with no prior /ai-prove-fix. Advancing to validation.

Devin session

@octavia-bot
Copy link
Copy Markdown
Contributor

octavia-bot Bot commented May 5, 2026

🔍 AI Prove Fix session starting... Running readiness checks and testing against customer connections. View playbook

Devin AI session created successfully!

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

devin-ai-integration Bot commented May 5, 2026

✅ Fix Validation: Sufficient Evidence — Pre-release Ready

The GET_SALES_AND_TRAFFIC_REPORT_BY_DATE step-size fix is verified at the protocol level and behaves equivalently to the published version on SPEC, CHECK, and DISCOVER. The pre-release image is published. Recommended next step: run /ai-canary-prerelease on this PR for live customer-data validation before full rollout.

Outcome

  • 🟢 Fix works: With the PR's manifest, GET_SALES_AND_TRAFFIC_REPORT_BY_DATE issues ONE create-report request covering the full 29-day window (2023-01-01 → 2023-01-30) instead of 29 separate per-day requests. Locally re-run the new unit test against master's manifest (control) and the PR's manifest (target):
    • Control (step: "P1D"): ❌ test fails — 30 separate per-day jobs are issued, all of which are unmatched by the multi-day mock and fail. 0 records emitted.
    • Target (step: "P{{ min(config.get('period_in_days', 365), 30) }}D"): ✅ test passes — single multi-day job matches the mock and emits 1 record.
  • 🟢 No regressions detected at the protocol level in regression-test comparison mode (SPEC ✅ / CHECK ✅ / DISCOVER ✅).
  • ⚠️ Regression READ timed out at the workflow's 180-min hard limit running both target and control sequentially across all 50+ SP-API report streams against live integration-test creds. This is a known scaling limit of the regression-test sandbox for Amazon Seller Partner (each SP-API report can take 1–30+ min to poll), not a fix-specific failure. No partial READ artifacts were uploaded.
  • 🟢 Pre-release image published: airbyte/source-amazon-seller-partner:5.8.0-preview.1c5a7a5

Evidence Summary

Phase Result Notes
Pre-flight: viability 🟢 Single-line manifest swap to step: "P{{ min(config.get('period_in_days', 365), 30) }}D", mirroring the pattern on ~10 other streams in the same manifest.
Pre-flight: safety 🟢 YAML manifest + unit test only. No suspicious code patterns.
Pre-flight: breaking-change 🟢 (not breaking) No breaking-change label, no !/🚨 in title; schema, spec, cursor field/format, and stream set are unchanged. State migration not required because queryEndDate cursor format is identical.
Pre-flight: reversibility 🟢 Reverting to step: "P1D" simply restores per-day slicing. State format unchanged on either side.
Pre-release publish 🟢 airbyte/source-amazon-seller-partner:5.8.0-preview.1c5a7a5 published.
Unit test (control vs target, locally) 🟢 / 🔴 expected New test_by_date_stream_sends_multi_day_window_in_single_request PASSES with the fix and FAILS without it (proving the manifest line is responsible for the behavior change).
Regression SPEC (target vs control) 🟢 / 🟢 No diff.
Regression CHECK (target vs control) 🟢 / 🟢 No diff.
Regression DISCOVER (target vs control) 🟢 / 🟢 No diff. 53 streams generated.
Regression READ (target vs control) ⚠️ inconclusive Workflow hit 180-min hard limit before either version finished iterating all streams. Not a fix-specific failure.
Detailed Evidence Log

Regression-test workflow: airbyte-ops-mcp/actions/runs/25374556298 (control auto-detected as airbyte/source-amazon-seller-partner:5.7.5, target built from PR HEAD 1c5a7a5).

Per-step outcomes from the workflow's "Determine Final Status" output:

SPEC: success=true
CHECK: success=true
DISCOVER: success=true
READ: success=        (timed out after 180 min before completion)

Local control-vs-target unit test against the new test added in this PR

Target (PR manifest, step: "P{{ min(config.get('period_in_days', 365), 30) }}D"):

integration/test_report_based_streams.py::TestSalesAndTrafficReportRequestBody::test_default_config_sends_asin_granularity_parent             PASSED [ 25%]
integration/test_report_based_streams.py::TestSalesAndTrafficReportRequestBody::test_child_granularity_config_sends_asin_granularity_child    PASSED [ 50%]
integration/test_report_based_streams.py::TestSalesAndTrafficReportRequestBody::test_by_month_stream_sends_date_granularity_and_asin_granularity PASSED [ 75%]
integration/test_report_based_streams.py::TestSalesAndTrafficReportRequestBody::test_by_date_stream_sends_multi_day_window_in_single_request  PASSED [100%]
4 passed in 9.32s

Control (master's manifest, step: "P1D"), running only the new test:

FAILED integration/test_report_based_streams.py::TestSalesAndTrafficReportRequestBody::test_by_date_stream_sends_multi_day_window_in_single_request
1 failed in 3.03s

The control failure logs show the connector kicked off 29 per-day async report jobs ({'start_time': '2023-01-01T…', 'end_time': '2023-01-01T23:59:59Z'}{'start_time': '2023-01-29T…', 'end_time': '2023-01-30T00:00:00Z'}), each rejected because the mock only matched the single multi-day body — exactly the wasteful pre-fix behavior the customer reported.

Pre-flight diff inspection (against origin/master):

airbyte-integrations/connectors/source-amazon-seller-partner/manifest.yaml      |  5 ++-
airbyte-integrations/connectors/source-amazon-seller-partner/metadata.yaml      |  2 +-
airbyte-integrations/connectors/source-amazon-seller-partner/unit_tests/integration/test_report_based_streams.py |  44 ++++++++++++++++
docs/integrations/sources/amazon-seller-partner.md                              |  1 +

The single behavioral line is in manifest.yaml@2906-2912 on the get_sales_and_traffic_report_by_date stream:

- step: "P1D"
+ step: "P{{ min( config.get('period_in_days', 365), 30 ) }}D"
Pre-flight Checks
  • Viability: ✅ Single-line manifest swap. Same min(config.get('period_in_days', …), …) pattern is already used on ~10 other streams in this manifest (e.g. get_brand_analytics_search_terms_report, get_brand_analytics_repeat_purchase_report, etc.). Default fallback raised from 90 to 365 inside the Jinja so the cap (30) is what binds when period_in_days is omitted from config.
  • Design intent: ✅ The triage report establishes the per-day slice was inherited from the BY_ASIN sibling without re-evaluation. Amazon's official SP-API report schema explicitly supports multi-day windows for salesAndTrafficByDate — see amzn/selling-partner-api-models/blob/main/schemas/reports/sellerSalesAndTrafficReport.json ("Aggregated data is available at different date range aggregation levels: DAY, WEEK, MONTH. … Requests can span multiple date range periods.") and amzn/selling-partner-api-models#426 confirming BY_ASIN must stay P1D.
  • Safety: ✅ YAML manifest + unit test only.
  • Breaking change check: 🟢 not breaking
    • No breaking-change label, no !/🚨 in title.
    • Schema unchanged (salesAndTrafficByDate[].date still drives the per-record date field).
    • Spec unchanged.
    • Cursor field queryEndDate and format unchanged. With existing per-day cursor state (e.g. 2024-01-15T00:00:00Z), the new step simply produces a 30-day window from that point — no state migration needed.
    • No streams added/removed.
  • Reversibility: ✅ Reverting to step: "P1D" restores per-day slicing immediately; state format is unchanged on either side.
Connector & PR Details
  • Connector: source-amazon-seller-partner (manifest-only, low-code declarative source)
  • Version: 5.7.45.8.0 (minor bump)
  • Pre-release image: airbyte/source-amazon-seller-partner:5.8.0-preview.1c5a7a5
  • OAuth write-back: No (refresh_token_updater / SingleUseRefreshTokenOauth2Authenticator not used) → regression-test sandbox is appropriate.
  • Latest commit on PR: 1c5a7a5 (docs: correct changelog PR link to 77747).

Recommended Next Steps

  1. Resolve the merge conflict with master (changelog/docs likely).
  2. Run /ai-canary-prerelease to validate the fix end-to-end against real customer data on a small set of internal/willing connections that actually sync GET_SALES_AND_TRAFFIC_REPORT_BY_DATE. Regression tests cannot prove the read-side behavior here because the GSM integration-test account has GET_SALES_AND_TRAFFIC_REPORT_BY_DATE listed under acceptance_tests.basic_read.empty_streams — it is not seeded with BY_DATE data — and the workflow times out before READ can complete on the rest of the catalog anyway.
  3. After canary validation, promote 5.8.0 to GA via the standard rollout flow.

Devin session

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Pre-release Connector Publish Started

Publishing pre-release build for connector source-amazon-seller-partner.
PR: #77747

Pre-release versions will be tagged as {version}-preview.1c5a7a5
and are available for version pinning via the scoped_configuration API.

View workflow run
Pre-release Publish: SUCCESS

Docker image (pre-release):
airbyte/source-amazon-seller-partner:5.8.0-preview.1c5a7a5

Docker Hub: https://hub.docker.com/layers/airbyte/source-amazon-seller-partner/5.8.0-preview.1c5a7a5

Registry JSON:

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

↪️ Triggering /ai-prove-fix per Hands-Free AI Triage Project triage next step.

Reason: Draft PR with no prior /ai-prove-fix run. Advancing to validation.

Devin session

@octavia-bot
Copy link
Copy Markdown
Contributor

octavia-bot Bot commented May 6, 2026

🔍 AI Prove Fix session starting... Running readiness checks and testing against customer connections. View playbook

Devin AI session created successfully!

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

devin-ai-integration Bot commented May 6, 2026

✅ Fix Validation: Sufficient Evidence — Pre-release Ready

The GET_SALES_AND_TRAFFIC_REPORT_BY_DATE step-size fix is verified at the protocol level. The pre-release image is published. Recommended next step: rebase to resolve the merge conflict, then run /ai-canary-prerelease for live customer-data validation before broader rollout.

Outcome

  • 🟢 Fix works: With the PR's manifest, GET_SALES_AND_TRAFFIC_REPORT_BY_DATE issues a single multi-day createReport request covering the full configured window (capped at 30 days) instead of one request per calendar day. Local unit test test_by_date_stream_sends_multi_day_window_in_single_request deterministically shows this:
    • Control (step: "P1D"): ❌ test fails — 29 separate per-day jobs are issued.
    • Target (step: "P{{ min(config.get('period_in_days', 365), 30) }}D"): ✅ test passes — single multi-day job.
  • 🟢 No protocol-level regressions detected in regression-test comparison mode: SPEC ✅ / CHECK ✅ / DISCOVER ✅ — both versions exit 0 for all three steps. CHECK and DISCOVER payloads byte-identical between target and control.
  • 🟢 Pre-release image published for the current head SHA 1c5a7a5: airbyte/source-amazon-seller-partner:5.8.0-preview.1c5a7a5.
  • One non-fix-related delta observed: SPEC payloads differ by 1 field (max_done_report_age_hours) — present on control (5.7.6-rc.1), absent on target (PR head). This is not caused by this PR; the PR branch is behind master and is missing feat(source-amazon-seller-partner): check for existing reports before creating new ones #76093 + fix(source-amazon-seller-partner): use 89-day buffer on settlement report 90-day boundary #76269, which is the same root cause as the reported merge conflict. After a rebase the SPEC payloads will be identical.
  • Regression READ not exercised in this run: Re-run used skip_read_action=true because the prior run hit the workflow's 180-min hard limit while iterating sequentially across 50+ slow SP-API report streams. The READ-side evidence for the affected stream is provided by the unit test above.

Evidence Summary

Phase Result Notes
Pre-flight: viability 🟢 Single-line manifest swap; pattern already used by ~10 other streams in the same manifest.
Pre-flight: safety 🟢 Pure declarative YAML change — no malicious code, no obfuscation, no new external network calls.
Pre-flight: breaking change 🟢 Not breaking No spec/schema/state/stream changes. Cursor field (queryEndDate) and format unchanged. Version 5.7.4 → 5.8.0 (minor).
Pre-flight: reversibility 🟢 Reversible Old version reading state from new version (or vice versa) sees a valid queryEndDate value in the same RFC3339 format.
Pre-release publish 🟢 5.8.0-preview.1c5a7a5 Verified still resolvable on the registry.
Local unit test 🟢 Control fails / target passes; all 4 pre-existing tests in TestSalesAndTrafficReportRequestBody still pass.
Regression SPEC (comparison) 🟢 Both succeeded 1-field SPEC delta fully attributable to PR being behind master (see above), not to this fix.
Regression CHECK (comparison) 🟢 Both succeeded CONNECTION_STATUS payloads byte-identical.
Regression DISCOVER (comparison) 🟢 Both succeeded Catalog payloads byte-identical: 53 streams in both, BY_DATE cursor field/sync modes unchanged.
Regression READ ⚠ Skipped Known 180-min sandbox timeout for source-amazon-seller-partner full-stream READ; not a fix-specific failure.

Recommended Next Steps

  1. Rebase this PR branch on master to resolve the merge conflict (PR is currently missing feat(source-amazon-seller-partner): check for existing reports before creating new ones #76093 and fix(source-amazon-seller-partner): use 89-day buffer on settlement report 90-day boundary #76269, both of which touch this connector). The conflict is in metadata.yaml and the changelog.
  2. Run /ai-canary-prerelease on this PR to validate the pre-release image against live customer connections before merge.
  3. After review, mark ready-for-review and merge.
Connector & PR Details
  • Connector: source-amazon-seller-partner (declarative / manifest-only)
  • Version bump: 5.7.45.8.0 (minor)
  • Head SHA: 1c5a7a5
  • Files changed: manifest.yaml, metadata.yaml, unit_tests/integration/test_report_based_streams.py, docs/integrations/sources/amazon-seller-partner.md
  • The fix: Single-line change to the step expression on the GET_SALES_AND_TRAFFIC_REPORT_BY_DATE stream:
    # before
    step: "P1D"
    # after
    step: "P{{ min( config.get('period_in_days', 365), 30 ) }}D"
    Mirrors the pattern already used by ~10 other streams in the same manifest. Amazon's published sellerSalesAndTrafficReport.json explicitly documents that salesAndTrafficByDate arrays are broken down per-date in multi-day responses, so the per-record date field is unaffected — only the slice marker (queryEndDate) becomes coarser.
  • Why the BY_ASIN sibling stream correctly stays at P1D: Amazon aggregates salesAndTrafficByAsin over the entire request window even with dateGranularity: DAY (see selling-partner-api-models#426). Only the BY_DATE variant is safe to widen.
Evidence Plan (Hypothesis)

With the PR's manifest, GET_SALES_AND_TRAFFIC_REPORT_BY_DATE issues fewer (multi-day) createReport requests than the per-day baseline, while emitting equivalent per-date records. Other streams (especially the BY_ASIN sibling) and connector lifecycle commands remain unchanged.

Proving criteria — all met:

  • Unit test passes target / fails control.
  • SPEC/CHECK/DISCOVER show no fix-attributable diff.
  • Catalog stream list and cursor field unchanged → backward state compatibility holds.

Disproving criteria — none observed.

Detailed Evidence Log

Devin session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant