Skip to content

Fixes #32978: preserve table column lineage during version consolidation - #32309

Merged
harshach merged 31 commits into
mainfrom
khoaihps-fix/improve-patch-table-api
Sep 10, 2026
Merged

Fixes #32978: preserve table column lineage during version consolidation#32309
harshach merged 31 commits into
mainfrom
khoaihps-fix/improve-patch-table-api

Conversation

@harshach

@harshach harshach commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #32978

A table column added earlier in the same editing session can lose its lineage during a later description-only PATCH. Version consolidation compares the persisted table with the older session baseline, which can report that still-existing column as deleted. This PR limits lineage mutations to the comparison against the actual persisted table and combines the nested column changes into one reconciliation after commit.

Related to #26674; continuation of #26848 by @khoaihps. The original contributor commits and authorship are preserved.

The reporter's follow-up identifies slow OpenSearch storage as the primary cause of the reported latency. This PR addresses the independent lineage correctness problem and redundant update work. End-to-end latency improvements have not been measured, and the original performance issue is not claimed fixed.

Type of change:

  • Bug fix

High-level design:

  • Mark the comparison against the persisted entity in EntityUpdater, reset that state on transaction retry, and gate both database lineage changes and deferred search reconciliation on it. Historical comparisons still run for version consolidation.
  • Collect nested column renames/deletions for the whole table. Update stored lineage inside the transaction and run one combined rename/delete search operation after a successful commit.
  • Allow at most three reconciliation attempts for version conflicts, refreshing the search snapshot before each retry. Do not replay overlapping rename maps, which can undo successful writes. Report unresolved conflicts, shard failures, and timeouts.
  • Preserve the existing column-match predicate, global search alias, and synchronous refresh behavior. Hash-based matching, index scoping, and refresh suppression are deferred from this PR.

No schema, API contract, or migration changes. Search reconciliation remains best effort after commit: persistent conflicts or search outages are logged; durable repair is outside this change.

Tests:

Use cases covered

  • Column deletion and case-only rename propagate to indexed lineage.
  • A rename reverted within the same session uses the persisted state as its baseline.
  • A description-only PATCH preserves lineage for a column added earlier in the session, in both the database and search.
  • Nested column changes, bulk column deletion, and a rename plus deletion in the same PATCH reconcile correctly.
  • Consecutive renames and rename-then-delete remain searchable with automatic refresh disabled in the test index.
  • Conflicts from an unrefreshed downstream write are retried without losing the concurrent edit.
  • Combined reconciliation updates both source and target FQNs and preserves unrelated mappings and metadata.

Unit tests

ColumnLineageReconcilerTest: 6 passed, covering retry bounds, refreshed snapshots, no-match/success, shard and transport failures, and overlapping renames. The new ColumnLineageReconciler helper has 21/21 lines covered (100%, JaCoCo 0.8.13). Whole-class coverage for the existing repositories and search managers was not measured by this focused run.

Backend integration tests

TableResourceIT (7 cases) and ColumnLineageReconciliationIT (5 cases) exercise real database and search backends:

Stack Result
MySQL 8.3 / Elasticsearch 9.3 12 passed, 0 failures/errors/skips
PostgreSQL 15 / OpenSearch 3.4 12 passed, 0 failures/errors/skips

Both suites ran against a clean build of the narrowed diff. The service artifact checksum was verified before and after execution.

Ingestion integration tests

Not applicable — no ingestion changes.

Playwright (UI) tests

Not applicable — no UI changes.

Manual testing performed

  • mvn clean install -pl openmetadata-service,openmetadata-integration-tests -am -DskipTests -Dcheckstyle.skip: all 11 reactor modules built successfully on Java 21.
  • mvn spotless:apply -pl openmetadata-service,openmetadata-integration-tests and pre-commit run: passed; no remaining formatting diff.
  • An isolated control disabled only the persisted-baseline guard in TableRepository, restoring main's unconditional lineage-update behavior. The session-added-column test failed at the lineage-preservation assertion after the description-only PATCH (1 test started, 1 expected failure, no aborted tests). The same test passed on both stacks with the guard enabled.

No end-to-end ingestion performance benchmark or full backend test-suite run was performed locally.

UI screen recording / screenshots:

Not applicable — no UI changes.

Checklist:

  • The reproduced correctness issue is linked via Fixes #32978. Related to #26674 is intentional: this change does not establish a fix for the reported slow-storage incident.
  • PR title follows Fixes <issue-number>: <short explanation> and describes the lineage correctness fix.
  • Non-obvious consolidation and retry behavior is documented in the code.
  • Regression tests cover the behavior being fixed.
  • Schema/migration and UI requirements: not applicable.

Khoa.DA and others added 17 commits March 30, 2026 18:13
…er pass, set refresh=false on updateColumnsInUpstreamLineage

- EntityRepository: toLowerCase(Locale.ROOT) to avoid locale-sensitive mis-keying (e.g. Turkish locale) — matches columnMatch's equalsIgnoreCase
- TableRepository: clear pendingRenameColumnFqns before each putAll to prevent conflicting A→B + B→A mappings when consolidateChanges runs updateInternal multiple times
- ElasticSearchEntityManager / OpenSearchEntityManager: change refresh=true → refresh=false in updateColumnsInUpstreamLineage, consistent with deleteColumnsInUpstreamLineage — same rationale applies: rename lineage cleanup does not need immediate read-after-write consistency
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…olerance, rename-path IT

- TableUpdater: override resetForRetryAttempt() so a deadlock replay
  re-enqueues the deferred column-lineage search flush. The retry
  prologue clears deferredReactOperations; without resetting the
  run-once guard the replayed attempt commits DB lineage but silently
  drops the search-index cleanup (the divergence #21536 originally
  fixed). Mirrors the override the other seven updaters already carry.
- ES/OS EntityManagers: ignoreUnavailable(true) on both column-lineage
  updateByQuery calls — with 8 concrete index names one missing index
  aborted cleanup for all of them, where the old "all" alias simply
  skipped missing members. Rewrote the wrapped refresh comments and
  moved the OpenSearch delete-path comment before its statement.
- SearchClient: document LineageRepository.getChildrenNames as the
  source of truth for COLUMN_LINEAGE_SEARCH_INDICES with a keep-in-sync
  note (13 other index mappings declare upstreamLineage but can never
  receive column lineage).
- TableResourceIT: cover the rename path via a case-only column rename
  (columnMatch is equalsIgnoreCase, so the column matches while its FQN
  changes) — updateColumnsInUpstreamLineage previously had no coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@harshach
harshach requested a review from a team as a code owner August 31, 2026 16:19
Copilot AI lite review requested due to automatic review settings August 31, 2026 16:19
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses severe latency in PATCH /api/v1/tables/{id} by ensuring column-lineage search-index cleanup work is deduplicated, scoped to the relevant indices, and made non-blocking, while also reducing column-matching complexity during updates.

Changes:

  • Scope column-lineage updateByQuery operations to a dedicated set of 8 indices (instead of the global "all" alias) and tolerate missing indices.
  • Make column-lineage updateByQuery non-blocking by disabling refresh, and deduplicate deferred lineage cleanup so it flushes exactly once post-commit (including retry-safety).
  • Optimize column matching in ColumnEntityUpdater.updateColumns by replacing per-column stream scans with a hashmap lookup; add integration coverage for delete + rename propagation to search.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
openmetadata-service/src/main/java/org/openmetadata/service/search/SearchClient.java Adds COLUMN_LINEAGE_SEARCH_INDICES to target only indices that can hold column-level lineage.
openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchEntityManager.java Uses ignoreUnavailable(true) and refresh=false for column-lineage update-by-query operations.
openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchEntityManager.java Uses ignoreUnavailable(true) and refresh=false for column-lineage update-by-query operations.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java Accumulates pending rename/delete FQNs and defers a single post-commit flush; resets guard state for retry attempts.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java Replaces O(n²) column matching with a hashmap lookup keyed by a ColumnKey record.
openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/TableResourceIT.java Adds IT coverage for delete + rename lineage propagation into search; introduces a helper to query upstreamLineage from the index.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Review (greptile, gitar) caught a regression in the deferred-flush
rewrite: clearing the pending collections on every pass meant the flush
read the FINAL consolidation pass, but revert() rebases that pass onto
the pre-session version. The search index sits at `original`, so the
final pass's FQNs match no indexed document — and a rename away and back
within the session yields a net-zero final diff, leaving the flush empty
and the index stranded on the intermediate FQN while the DB moved on.

Accumulate from the first pass instead, which is the only one that diffs
against the state the index reflects (and the sole pass when consolidation
does not apply). This also keeps the revert pass out of the flush, so a
column added earlier in the session is no longer surfaced as a delete —
the spurious-delete hazard that exists on main, where every pass enqueued
its own search op. resetForRetryAttempt() zeroes the pass counter so a
deadlock replay starts from the baseline pass.

Also from review:
- putIfAbsent in the origColumns lookup map, preserving the first-match
  semantics of the stream findAny() it replaced on duplicate keys
- close the search response stream in the IT helper, which the new
  polling tests exercise repeatedly

Adds test_revertedColumnRenameWithinSessionPropagatesInSearch covering
the net-zero consolidation path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 31, 2026 16:33
Most column deletes and renames have nothing downstream referencing them, so
updatedDocuments == 0 is the ordinary outcome during ingestion, not an anomaly.
Warning on it produced noisy and potentially alert-triggering logs on a routine
path. WARN is now reserved for version conflicts and ERROR for failures.

The case still carries a diagnostic value it is worth keeping the message for --
it is also what a missing index or a misresolved index selector looks like --
but that failure mode is pinned at build time by ColumnLineageSearchIndicesTest,
which ties the selector to the resolver registry, so it does not need a runtime
warning to catch it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 5, 2026 13:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes core entity-update/lineage reconciliation behavior across persistence and search backends, warranting final human verification despite strong test coverage.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

openmetadata-service/src/test/java/org/openmetadata/service/search/ColumnLineageSearchIndicesTest.java:69

  • This assertion hardcodes the index name separator as "" ("clusterx") even though the separator is defined centrally as IndexMapping.INDEX_NAME_SEPARATOR. Using the constant makes the test resilient if the separator ever changes (or if a different separator is introduced for other index classes), while keeping the same intent.
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The performance fix is correctly scoped, preserves lineage correctness via baseline-pass gating, and is backed by meaningful integration tests covering delete/rename/revert and bulk/nested scenarios.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Column-lineage reconciliation update-by-query still forces a blocking refresh in both ES and OpenSearch managers, which reintroduces the primary latency driver this PR is intended to remove.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/ColumnLineageReconciliationIT.java:121

  • Add an explicit index refresh helper so tests can control visibility deterministically when refresh_interval is disabled (used here to model stale snapshots / version conflicts).
    private JsonNode readSource() throws IOException {
      return request("GET", "/_doc/target", null).path("_source");
    }
  • Files reviewed: 17/17 changed files
  • Comments generated: 3
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

ColumnLineageReconciler currently disables retries too broadly for rename maps (can skip safe retries and leave avoidable version conflicts), so the retry-safety logic should be corrected before approval.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

openmetadata-service/src/main/java/org/openmetadata/service/search/ColumnLineageReconciler.java:29

  • retrySafe disables conflict retries whenever any rename target is also a rename source (renames.values().stream().noneMatch(renames::containsKey)), which blocks retries for safe rename chains (e.g. a->b, b->c) even though the comment only calls out direct swaps (a->A, A->a). This can leave avoidable version conflicts unreconciled.
    openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchEntityManager.java:943
  • The comment above refresh(!renames.isEmpty()) says conflict retries cannot recover without a refresh, but conflict retries already call indices().refresh(...) via ColumnLineageReconciler.reconcile(...). As written, the comment is misleading about why refresh is needed here.
    openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchEntityManager.java:1007
  • The comment above the conditional refresh claims conflict retries cannot recover without it, but retries already refresh explicitly in ColumnLineageReconciler.reconcile(...). This comment should explain the actual reason (making renamed FQNs searchable for subsequent update-by-query calls) to avoid misleading future changes.
  • Files reviewed: 17/17 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Restore predicate-based column matching, the global search alias, and
synchronous refreshes. Remove the lookup and index-selection abstractions
and the tests specific to those optional optimizations.

Retain persisted-baseline lineage reconciliation, nested change collection,
combined search updates, and bounded conflict recovery.
@harshach

harshach commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

Narrowed this PR in 7be9b80 following the reporter's clarification about slow OpenSearch storage.

The PR retains the independently justified lineage fixes: apply mutations only against the persisted baseline, collect nested column changes, reconcile renames/deletions together after commit, and handle version conflicts with bounded retries and accurate failure reporting.

The optional optimizations are removed: column matching uses the original predicate scan; search cleanup uses the existing global alias; both engines retain synchronous refresh. The lookup-key and index-selection abstractions and their dedicated tests are removed as well.

Validation on the narrowed diff: 12 integration cases passed on MySQL 8.3/Elasticsearch 9.3, 12 passed on PostgreSQL 15/OpenSearch 3.4, and all 6 retry unit tests passed. The clean backend build, Spotless, and pre-commit checks passed. A control that disables only the persisted-baseline guard fails the session-added-column lineage-preservation test; the same test passes with the guard on both stacks.

The title and description now target the reproduced correctness bug, #32978. #26674 remains related; this PR makes no claim to resolve the storage-related latency or to deliver a measured end-to-end performance improvement.

The required Shipping metadata for #32978 is still pending because the current GitHub token has read-only project access. The corresponding values on the original tracking issue are Status: In Review / QA, Source: OSS, Priority: P1, Domain: Platform, Release: 2.1.0.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new reconciliation path still forces refresh and still targets the global “all” alias in the changed code paths, which undermines the stated performance/scoping goals and risks reintroducing the original latency.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 13/13 changed files
  • Comments generated: 3
  • Review effort level: Lite

@harshach

harshach commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

The Collate failure in run 34251264490 comes from the PR branch missing an upstream validation change.

  • The run built Collate 78de89516e1980add5587ea27d2c4c11edeab784 with OpenMetadata PR head 7be9b807bdad0e81b0ad05fedad1b255957df0fd.
  • CollateIngestionPipelineIT.testPipelineCreation_EmptySourceConfig_RejectsMissingType expects HTTP 400 for sourceConfig.config = {}, but this branch returns HTTP 201. It is the single failure among 489 integration tests (6 skipped).
  • OpenMetadata #29566 added validateSourceConfigHasType() in commit 27063928f7f2847d56b55afda460fd1cb150cf66.
  • Collate #6300 changed the assertion to require that validation. Both changes merged on September 7.
  • Git ancestry confirms the validation commit is in current OpenMetadata main (69fd965d8271305060058a5b774a3ab895ff417d) and absent from this PR head. Collate delegates preparation to the OpenMetadata repository, so the missing superclass validation explains the observed 201 response.

The next step is to sync this branch with main and rerun the Collate compatibility check. This failure requires no change to the lineage implementation or to the test expectation.

Bring in OpenMetadata #29566, which Collate's existing integration test
requires. Preserve the table column lineage fix without changing its scope.
@harshach

harshach commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

Merged OpenMetadata main (d96acdd095) into this PR in a5b7dfd4d0047e2b6d9ac102d551a8e87aefef51, bringing in the source-config validation from #29566 that Collate's existing test requires. The merge was conflict-free and preserves the existing 13-file lineage diff.

Validation on the merged tree:

  • Clean Java 21 backend reactor build: all 11 modules passed.
  • IngestionPipelineRepositoryTest and ColumnLineageReconcilerTest: 48 tests passed.
  • MySQL + Elasticsearch integration tests: all 4 passed, covering missing-type rejection on create/update/PATCH and lineage preservation during session consolidation.
  • Spotless and the PR's pre-commit checks passed.

The push triggers a fresh Collate compatibility check against the updated commit. No additional Collate PR or test-expectation change is needed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

A null deleted-column FQN can currently trigger an NPE during lineage change aggregation, which would break PATCH/PUT flows on legacy data.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 13/13 changed files
  • Comments generated: 1
  • Review effort level: Lite

Skip null FQNs before collecting deleted columns for lineage reconciliation
so legacy rows do not fail PATCH and PUT with List.copyOf's null rejection.

Cover both API paths with a legacy row and verify that valid deleted
columns still lose their stored and indexed lineage.
@gitar-bot

gitar-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Fixes table column lineage corruption during version consolidation by limiting lineage mutations to comparisons against the persisted table state and deferring search reconciliation until after commit. Addresses net-zero consolidated renames/deletes leaving search stale, HashMap column lookup keeping last match instead of first, and reconcile flush behavior. All integration tests pass on MySQL/Elasticsearch and PostgreSQL/OpenSearch stacks.

✅ 4 resolved
Bug: Net-zero consolidated rename/delete leaves search lineage stale

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java:2347-2361 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java:8996-9010
TableUpdater.entitySpecificUpdate() clears pendingDeletedColumnFqns/pendingRenameColumnFqns at the start of every pass and flushes exactly once from the FINAL pass. During in-session consolidation, revert() drives the last updateInternal from previous (session baseline) to the final updated. A rename-back (e.g. col A→B committed in an earlier request, then B→A within the consolidation window) or a delete-then-restore produces a net-zero final diff, so the pending collections are empty and no search update is flushed — yet a prior committed request already propagated the intermediate state (B) into downstream upstreamLineage.columns. The result is search showing B while the DB column is A. The previous code deferred a search op on every pass (including the revert/intermediate passes that surface the B→A mapping), so it happened to correct the search index; the new per-pass clear + single final flush drops that correction, reintroducing the DB/search divergence #21536 addressed. Consider accumulating rename/delete ops across the revert and intermediate passes (deduplicated) rather than only reading the final net pass, or otherwise ensuring the flush reflects every committed intermediate FQN transition.

Edge Case: HashMap column lookup keeps last match vs. findAny's first

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java:10630-10637
The new origColumnByKey map in updateColumns overwrites on duplicate keys (put keeps the last column with a given lowercased-name/dataType/arrayDataType), whereas the replaced origColumns.stream().filter(columnMatch).findAny() returned the first match. Within one column level column names are normally unique so this is low-impact, but if two sibling columns collide on (name, dataType, arrayDataType) the carried-forward metadata now attaches to a different original column than before. If strict parity is desired, use putIfAbsent to preserve first-match semantics.

Performance: reconcile flush switched back to refresh=true on request thread

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchEntityManager.java:941-955 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchEntityManager.java:1005-1019
buildColumnLineageRequest in both engines sets refresh=true (ElasticSearchEntityManager.java:954, OpenSearchEntityManager.java:1020), whereas the pre-reconcile code used refresh=false — the exact optimization the PR's root-cause #3 introduced to stop blocking the request thread on a shard refresh. The column-lineage flush runs synchronously on the request thread post-commit (via deferReactOperation), so refresh=true reintroduces a synchronous shard refresh across the 8 column-lineage indices on every column-touching PATCH. It is no longer needed for retry correctness because ColumnLineageReconciler already calls an explicit indices().refresh() between conflict retries, and nothing reads the result in-request. If the intent is only cross-PATCH visibility during sequential ingestion, confirm that benefit outweighs the reintroduced per-request refresh cost; otherwise revert the request to refresh=false and rely on the retry path's explicit refresh.

Performance: Lineage flush reverts to GLOBAL_SEARCH_ALIAS cluster-wide scan

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java:2470-2471 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TableRepository.java:43
This commit switches flushColumnLineageSearchUpdates back to reconcileColumnsInUpstreamLineage(GLOBAL_SEARCH_ALIAS, ...) and deletes the COLUMN_LINEAGE_SEARCH_INDICES scoping (ColumnLineageChildren.java). The post-commit update-by-query again fans out across the full "all" alias (~30+ indices) instead of the ~8 that can hold column lineage — the exact cluster-wide scan that issue #26674 (49–99s PATCH latency) set out to eliminate. Combined with the reintroduced blocking refresh, the final state no longer delivers the search-side latency reduction the PR description advertises. This appears intentional per the commit message ("narrow to correctness safeguards"); if so, confirm the PR/issue scope reflects that the index-scoping optimization was dropped.

Options

Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes core entity update/consolidation behavior and search update-by-query reconciliation paths, so it warrants final human maintainer review despite strong targeted test coverage.

Review details
  • Files reviewed: 13/13 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

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

Labels

backend safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Table column lineage can be deleted during session consolidation

6 participants