This is an automated email from the ASF dual-hosted git repository.
danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hudi.git
The following commit(s) were added to refs/heads/master by this push:
new c010ad7a8764 fix(agent): treat existing-table identity mismatch as
evidence conflict (#20410)
c010ad7a8764 is described below
commit c010ad7a8764a6c2413bbf47298968340df4f04b
Author: fhan <[email protected]>
AuthorDate: Mon Oct 26 11:38:49 2026 +0800
fix(agent): treat existing-table identity mismatch as evidence conflict
(#20410)
Co-authored-by: fhan <[email protected]>
---
hudi-agent-gateway/tests/test_hudi_architect_skill.py | 12 ++++++++++--
.../references/flink-existing-table-reconciliation.md | 7 +++++--
.../skills/hudi-architect/references/flink-warnings.md | 5 +++--
.../skills/hudi-architect/validate_flink_existing_table.py | 3 ++-
4 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/hudi-agent-gateway/tests/test_hudi_architect_skill.py
b/hudi-agent-gateway/tests/test_hudi_architect_skill.py
index bd480490fae9..4765386c3528 100644
--- a/hudi-agent-gateway/tests/test_hudi_architect_skill.py
+++ b/hudi-agent-gateway/tests/test_hudi_architect_skill.py
@@ -1275,7 +1275,9 @@ def
test_pr5_timestamp_partition_layout_difference_is_not_deployment_only(
]
-def test_pr5_table_path_has_independent_provenance(tmp_path: Path) -> None:
+def test_pr5_identity_path_disagreement_is_unverified_evidence_conflict(
+ tmp_path: Path,
+) -> None:
envelope = json.loads(_read(PR5_FIXTURE_DIR /
"compatible_mutable_cow.json"))
envelope["evidence"][4]["facts"]["table_path"] =
"file:///tmp/another-table"
@@ -1283,11 +1285,17 @@ def
test_pr5_table_path_has_independent_provenance(tmp_path: Path) -> None:
assert result.returncode == 1, result.stderr
assessment = json.loads(result.stdout)
+ assert assessment["status"] == "REVIEW_REQUIRED"
+ assert assessment["reconciliation_result"] == "UNVERIFIED"
+ assert assessment["change_disposition"] == "UNVERIFIED"
+ assert assessment["finding_codes"] == ["FLINK_EXISTING_EVIDENCE_CONFLICT"]
comparison = next(
item for item in assessment["comparisons"]
if item["field"] == "table_identity.table_path"
)
- assert comparison["result"] == "CONFLICT"
+ assert comparison["desired"] ==
envelope["desired_contract"]["table"]["path"]
+ assert comparison["observed"] == "file:///tmp/another-table"
+ assert comparison["result"] == "UNVERIFIED"
assert comparison["source_ids"] == ["identity-1"]
diff --git
a/hudi-ai-operator/skills/hudi-architect/references/flink-existing-table-reconciliation.md
b/hudi-ai-operator/skills/hudi-architect/references/flink-existing-table-reconciliation.md
index d518249f3f78..a857a5588e80 100644
---
a/hudi-ai-operator/skills/hudi-architect/references/flink-existing-table-reconciliation.md
+++
b/hudi-ai-operator/skills/hudi-architect/references/flink-existing-table-reconciliation.md
@@ -65,7 +65,10 @@ contract. If redaction removes a load-bearing fact, leave it
incomplete.
- `hudi_table_identity` identifies the concrete `table_path` at which the
artifacts were observed.
The path is not a persisted `hoodie.properties` key. Every evidence envelope
must repeat the
desired target path. The validator excludes another table's facts before
aggregation, then
- compares the accepted evidence scope with both the desired path and the
identity fact.
+ compares the accepted evidence scope with both the desired path and the
identity fact. If an
+ in-scope envelope's identity fact names another path, treat the item as
contradictory evidence:
+ emit `FLINK_EXISTING_EVIDENCE_CONFLICT` and leave reconciliation and change
disposition
+ `UNVERIFIED`. Do not infer that the target table requires migration.
- `hoodie_properties` is authoritative for persisted table name, type, table
version, timeline
layout, file format, record key, ordering fields, merge mode, partition
fields, key-generator
type, and hive-style/URL-encoded partitioning flags. Normalize an effective
value only when
@@ -160,7 +163,7 @@ Run:
python validate_flink_existing_table.py --input <reconciliation.json>
```
-See
`../../../tests/fixtures/hudi_architect/flink_pr5/compatible_mutable_cow.json`
for a complete
+See
`hudi-agent-gateway/tests/fixtures/hudi_architect/flink_pr5/compatible_mutable_cow.json`
for a complete
synthetic envelope. Its timestamps and digests are fixture data, not
production evidence.
A compatible result exits zero even though `executable_eligible` is false.
Other results exit one.
diff --git
a/hudi-ai-operator/skills/hudi-architect/references/flink-warnings.md
b/hudi-ai-operator/skills/hudi-architect/references/flink-warnings.md
index 977b20fb8e58..7f1a153dd9a6 100644
--- a/hudi-ai-operator/skills/hudi-architect/references/flink-warnings.md
+++ b/hudi-ai-operator/skills/hudi-architect/references/flink-warnings.md
@@ -79,8 +79,9 @@ digest, or contains a credential-shaped fact.
## FLINK_EXISTING_EVIDENCE_CONFLICT
-**Trigger:** Two observations disagree, an evidence envelope identifies
another table path, or a
-Flink DDL disagrees with authoritative Hudi table config or physical schema.
+**Trigger:** Two observations disagree, an evidence envelope identifies
another table path, an
+in-scope envelope's identity fact names another path, or a Flink DDL disagrees
with authoritative
+Hudi table config or physical schema.
**Message:** Contradictory evidence cannot be silently merged. Persisted table
config and the Hudi
table schema remain authoritative, but the discrepancy needs review.
diff --git
a/hudi-ai-operator/skills/hudi-architect/validate_flink_existing_table.py
b/hudi-ai-operator/skills/hudi-architect/validate_flink_existing_table.py
index 5533b12578bc..f8a2069f96ae 100644
--- a/hudi-ai-operator/skills/hudi-architect/validate_flink_existing_table.py
+++ b/hudi-ai-operator/skills/hudi-architect/validate_flink_existing_table.py
@@ -813,7 +813,8 @@ def assess_reconciliation(
"table_identity.table_path",
desired_table.get("path"),
observations.get("hudi_table_identity", {}).get("table_path"),
- mismatch_code="FLINK_EXISTING_TABLE_PROPERTY_CONFLICT",
+ mismatch_code="FLINK_EXISTING_EVIDENCE_CONFLICT",
+ mismatch_result="UNVERIFIED",
assessment=assessment,
)
_add_comparison(