Fixes #30908: Add Conversation V2 and activity replies - #30909
Conversation
|
Too many files changed for review (318 files, 100 file limit). Bypass the limit by tagging |
✅ PR checks passedThe linked issue has a description and all required Shipping project fields set. Thanks! |
✅ TypeScript Types Auto-UpdatedThe generated TypeScript types have been automatically updated based on JSON schema changes in this PR. |
🔴 Playwright Results — workflow failedValidated commit ✅ 1877 passed · ❌ 4 failed · 🟡 4 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky ❌ Action needed: test(s) failed on every attempt against this PR’s validated commit — see Genuine Failures below. These are test failures, not CI budget or infrastructure issues. PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 3h 41m 43s ⏱️ Max setup 4m 18s · max shard execution 19m 57s · max shard-job elapsed before upload 23m 23s · reporting 11s 🌐 193.69 requests/attempt · 2.29 app boots/UI scenario · 33.00% common-shard skew Optimization targets still in progress:
Genuine Failures (failed on all attempts)❌
|
This reverts commit da9a1aa. The extra workers were treating a symptom. #31244 fixes the actual cause - a 5s Awaitility poll delay per root in NamespaceCleanup - and its lanes run green at the original 4 workers: parallel (mysql-elasticsearch) 32m45s parallel (postgres-es-redis) 31m35s parallel (postgres-opensearch) 39m30s all well inside the 65m budget, against the timeouts we were seeing before. So the parallelism bump buys nothing, and this branch no longer needs to carry a .github/workflows change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
| Count | Rule |
|---|---|
| 58 | sonarjs/no-duplicate-string |
| 33 | react-hooks/exhaustive-deps |
| 18 | sonarjs/no-clear-text-protocols |
| 15 | sonarjs/cyclomatic-complexity |
| 9 | openmetadata-imports/review-sequential-api-calls |
| 8 | sonarjs/expression-complexity |
| 7 | openmetadata-imports/no-lower-layer-page-imports |
| 7 | @typescript-eslint/no-explicit-any |
| 5 | sonarjs/no-nested-conditional |
| 4 | sonarjs/cognitive-complexity |
All findings
| Location | Rule | Message | |
|---|---|---|---|
| 🟡 | src/components/ActivityFeed/ActivityFeedCard/FeedCardBody/FeedCardBodyNew.tsx:126:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has unnecessary dependencies: 'isPost' and 'postMessage'. Either exclude them or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedCard/FeedCardBody/FeedCardBodyNew.tsx:172:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has missing dependencies: 'handleSave', 'onEditCancel', and 't'. Either include them or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:85:30 |
sonarjs/cognitive-complexity |
Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed. |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:85:30 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 47 which is greater than 10 authorized.","cost":37,"secondaryLocations":[{"line":85,"column":29,"endLine":85,"endColumn |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:100:7 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (5) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:216:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 'showThread'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:245:9 |
react-hooks/exhaustive-deps |
The 'closeFeedEditor' function makes the dependencies of useMemo Hook (at line 294) change on every render. Move it inside the useMemo callback. Alternatively, |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:250:5 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (4) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx:553:21 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (4) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/CommentCard.component.tsx:58:26 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 12 which is greater than 10 authorized.","cost":2,"secondaryLocations":[{"line":58,"column":25,"endLine":58,"endColumn" |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/CommentCard.component.tsx:94:9 |
react-hooks/exhaustive-deps |
The 'onUpdate' function makes the dependencies of useCallback Hook (at line 103) change on every render. Move it inside the useCallback callback. Alternatively, |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/CommentCard.component.tsx:132:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has missing dependencies: 'defaultValue' and 'reply.message'. Either include them or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedCardNew/CommentCard.test.tsx:115:9 |
sonarjs/no-clear-text-protocols |
Using http protocol is insecure. Use https instead. |
| 🟡 | src/components/ActivityFeed/ActivityFeedDrawer/ActivityFeedDrawer.tsx:62:31 |
sonarjs/no-duplicate-string |
Define a constant instead of duplicating this literal 3 times. |
| 🟡 | src/components/ActivityFeed/ActivityFeedDrawer/ActivityFeedDrawer.tsx:121:17 |
@typescript-eslint/no-non-null-assertion |
Forbidden non-null assertion. |
| 🟡 | src/components/ActivityFeed/ActivityFeedDrawer/ActivityFeedDrawer.tsx:133:19 |
@typescript-eslint/no-non-null-assertion |
Forbidden non-null assertion. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:232:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'fetchTestCaseResolution'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:266:7 |
sonarjs/cognitive-complexity |
Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:266:7 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 21 which is greater than 10 authorized.","cost":11,"secondaryLocations":[{"line":266,"column":6,"endLine":266,"endColum |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:384:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 't'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:431:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 't'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:470:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has missing dependencies: 'setActiveTask' and 't'. Either include them or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:605:9 |
react-hooks/exhaustive-deps |
The 'updateReactions' function makes the dependencies of useMemo Hook (at line 928) change on every render. Move it inside the useMemo callback. Alternatively, |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:629:11 |
openmetadata-imports/review-sequential-api-calls |
Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:630:11 |
openmetadata-imports/review-sequential-api-calls |
Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:690:9 |
react-hooks/exhaustive-deps |
The 'updateEditorFocus' function makes the dependencies of useMemo Hook (at line 928) change on every render. Move it inside the useMemo callback. Alternatively |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:698:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'setActiveThread'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:705:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'setActiveTask'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx:780:28 |
sonarjs/no-nested-functions |
Refactor this code to not nest functions more than 4 levels deep. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:117:26 |
sonarjs/cognitive-complexity |
Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:117:26 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 34 which is greater than 10 authorized.","cost":24,"secondaryLocations":[{"line":117,"column":25,"endLine":117,"endColu |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:258:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'onUpdateFeedCount'. Either include it or remove the dependency array. If 'onUpdateFeedCount' changes too often |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:261:48 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 15 which is greater than 10 authorized.","cost":5,"secondaryLocations":[{"line":261,"column":47,"endLine":261,"endColum |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:271:11 |
sonarjs/no-nested-conditional |
Extract this nested ternary operation into an independent statement. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:330:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'userId'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:597:5 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 't'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:628:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'activeTab'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:722:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 't'. Either include it or remove the dependency array. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:861:15 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (4) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:874:10 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (5) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:876:13 |
sonarjs/no-nested-conditional |
Extract this nested ternary operation into an independent statement. |
| 🟡 | src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx:901:10 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (5) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:79:4 |
sonarjs/cognitive-complexity |
Refactor this function to reduce its Cognitive Complexity from 26 to the 15 allowed. |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:79:4 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 21 which is greater than 10 authorized.","cost":11,"secondaryLocations":[{"line":79,"column":3,"endLine":79,"endColumn" |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:262:13 |
sonarjs/no-nested-conditional |
Extract this nested ternary operation into an independent statement. |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:280:14 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (4) used in the expression (maximum allowed 3). |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:297:15 |
sonarjs/no-nested-conditional |
Extract this nested ternary operation into an independent statement. |
| 🟡 | src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadPanelBody.tsx:339:17 |
sonarjs/no-nested-conditional |
Extract this nested ternary operation into an independent statement. |
| 🟡 | src/components/ActivityFeed/Shared/ActivityFeedActions.tsx:52:30 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 15 which is greater than 10 authorized.","cost":5,"secondaryLocations":[{"line":52,"column":29,"endLine":52,"endColumn" |
| 🟡 | src/components/Announcement/AnnouncementThreadBody.component.tsx:32:1 |
openmetadata-imports/no-circular-imports |
This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency. |
… and 127 more. Run make ui-checkstyle-changed locally for the full list.
Fix locally (fast - only checks files changed in this branch):
make ui-checkstyle-changed…ies-30909 # Conflicts: # ingestion/src/metadata/ingestion/source/pipeline/prefect/metadata.py
_result_list already guarded against a non-dict response, but then indexed
response["data"] and response["paging"]["total"]. An error body decodes to a
dict too, so any payload without those keys raised KeyError instead of falling
back to an empty EntityList.
Read both through .get with defaults. `or {}` / `or []` rather than a plain
default so an explicit null paging or data also degrades instead of raising.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lies # Conflicts: # .github/scripts/select_playwright_tests.py # bootstrap/sql/migrations/native/2.0.0/mysql/postDataMigrationSQLScript.sql # bootstrap/sql/migrations/native/2.0.0/mysql/schemaChanges.sql # bootstrap/sql/migrations/native/2.0.0/postgres/postDataMigrationSQLScript.sql # bootstrap/sql/migrations/native/2.0.0/postgres/schemaChanges.sql # openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ColumnSearchIndexIT.java # openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java # openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertsRuleEvaluator.java # openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java # openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v200/Migration.java # openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v200/Migration.java # openmetadata-service/src/main/java/org/openmetadata/service/resources/activity/ActivityResource.java # openmetadata-service/src/test/java/org/openmetadata/service/events/subscription/AlertUtilTest.java # openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityAPI.spec.ts # openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ActivityFeed.spec.ts # openmetadata-ui/src/main/resources/ui/playwright/utils/activityAPI.ts # openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts # openmetadata-ui/src/main/resources/ui/playwright/utils/widgetFilters.ts # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCard/ActivityFeedCard.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.test.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedCardNew/ActivityFeedcardNew.component.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedList/ActivityFeedListV1New.component.test.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedList/ActivityFeedListV1New.component.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedPanel/ActivityPanelBody.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.test.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProviderContext.interface.ts # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.test.tsx # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.component.tsx # openmetadata-ui/src/main/resources/ui/src/components/Customization/GenericProvider/GenericProvider.interface.ts # openmetadata-ui/src/main/resources/ui/src/components/Customization/GenericProvider/GenericProvider.tsx # openmetadata-ui/src/main/resources/ui/src/mocks/ActivityFeedProvider.mock.tsx # openmetadata-ui/src/main/resources/ui/src/rest/feedsAPI.ts # openmetadata-ui/src/main/resources/ui/src/utils/DataQuality/TestSummaryGraphUtils.ts # openmetadata-ui/src/main/resources/ui/src/utils/FeedUtilsPure.ts
…lies # Conflicts: # bootstrap/sql/migrations/native/2.1.0/mysql/schemaChanges.sql # bootstrap/sql/migrations/native/2.1.0/postgres/schemaChanges.sql # openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java # openmetadata-ui/src/main/resources/ui/playwright/utils/activityFeed.ts # openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.tsx # openmetadata-ui/src/main/resources/ui/src/components/NotificationBox/NotificationFeedCard.test.tsx
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 109 out of 312 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
ingestion/src/metadata/ingestion/source/pipeline/prefect/metadata.py:373
- In Prefect pipeline status mapping,
_parse_timestampalready returns aTimestamp(it wraps the parsed millis withTimestamp(...)), but_build_task_statuswraps that result again via_as_timestamp(...). This extra conversion is inconsistent with other pipeline sources (e.g., dbtcloud) and could break ifTimestampis not a plainintalias.
Related occurrences in the same file: _build_pipeline_status uses timestamp=Timestamp(start_time) and endTime=_as_timestamp(end_time), and _as_timestamp itself is typed as accepting int | None even though the current call sites pass Timestamp | None.
| "activityCommentsRetentionPeriod": { | ||
| "title": "Activity Comments Retention Period (days)", | ||
| "description": "Enter the retention period for comments on Activity Events in days. Use 0 to retain activity comments forever.", | ||
| "type": "integer", | ||
| "default": 0, |
| "appConfiguration": { | ||
| "changeEventRetentionPeriod": 7, | ||
| "activityThreadsRetentionPeriod": 60, | ||
| "activityCommentsRetentionPeriod": 0, | ||
| "profileDataRetentionPeriod": 1440, | ||
| "testCaseResultsRetentionPeriod": 1440 | ||
| }, |
| $$section | ||
| ### Activity Comments Retention Period (days) $(id="activityCommentsRetentionPeriod") | ||
|
|
||
| Enter the retention period for comments on Activity Events in days. Use 0 to retain activity comments forever. | ||
|
|
||
| $$ | ||
|
|
||
| $$section |
Code Review ✅ Approved 8 resolved / 8 findingsReplaces the legacy FeedRepository and runtime with schema-first Conversation V2 APIs and activity replies. Addressed multiple data integrity, migration, and response handling findings. ✅ 8 resolved✅ Bug: Patching a conversation wipes all root reactions
✅ Performance: list() builds the count filter SQL twice
✅ Edge Case: One malformed receiver URI drops all webhook recipients
✅ Bug: MySQL CREATE INDEX statements are not idempotent, break re-migration
✅ Edge Case: Domain test-suite match reads payload, not stored test suites
...and 3 more resolved from earlier reviews OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
|
|



Describe your changes:
Fixes #30908
I replaced the legacy FeedRepository and
/v1/feedruntime with schema-first Conversation V2 APIs so user conversations and ActivityEvent replies have explicit ownership, authorization, storage, and lifecycle semantics while tasks and announcements remain on their dedicated APIs. The UI now loads activity replies lazily by ActivityEvent ID and uses dedicated conversation clients without synthetic roots or duplicate first replies.Type of change:
High-level design:
Conversation,ConversationReply,ConversationSource,ConversationFilterType, andCreateConversationmodels, with a dedicated repository owning authorization, validation, transactions, persistence, events, mentions, domain projection, cleanup, and hydration; REST resources only bind parameters and delegate.aboutvalue.2.0.0; legacy Conversation threads are migrated, Task and Announcement rows remain owned by their migrations, Chatbot rows remain recoverable from the archive, and subscription-compatible thread/post event enum values are retained withentityType=conversation./v1/feedhas no compatibility alias, so clients must cut over to/v1/conversations,/v1/activity,/v1/tasks, or/v1/announcements.Tests:
Use cases covered
aboutisolation; deleted/expired targets; reaction ownership; retention defaults and explicit cleanup.Unit tests
ConversationRepositoryTest,ConversationFilterTest,ConversationMigrationTest,ConversationReferenceMigrationTest,ActivityStreamRepositoryTest, formatter/retention tests, Conversation REST-client tests, and Activity Feed provider/card/action/drawer tests.Backend integration tests
openmetadata-integration-tests/for new/changed API endpoints.ConversationResourceIT,ActivityResourceIT,ConversationSchemaMigrationIT, andDataRetentionAppIT; legacy Feed suites were migrated or removed.Ingestion integration tests
Playwright (UI) tests
openmetadata-ui/.../ui/playwright/for UI changes.playwright/CONVERSATION_V2_TRACEABILITY.md; 141 selected scenarios and their setup dependencies collected successfully.Manual testing performed
Not performed; validation used repository units plus real MySQL/PostgreSQL application integration tests and Playwright collection.
UI screen recording / screenshots:
Not yet attached. This PR is opened as a draft and needs an end-to-end UI recording before it is marked ready for review.
Checklist:
Fixes <issue-number>: <short explanation>Fixes #<issue-number>above.Backward-Incompatible-Change.