Skip to content

feat: Correctly set fields on Remove action when AMT is enabled - #3318

Merged
Fokko merged 3 commits into
delta-io:mainfrom
Fokko:fd-remove
Sep 17, 2026
Merged

Fokko merged 3 commits into
delta-io:mainfrom
Fokko:fd-remove

Conversation

@Fokko

@Fokko Fokko commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

What changes are proposed in this pull request?

As described in the Delta RFC:

https://github.com/delta-io/delta/blob/master/protocol_rfcs/iceberg-v4-metadata.md#remove-file

How was this change tested?

@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.22222% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.51%. Comparing base (c11be8a) to head (c4b96c0).

Files with missing lines Patch % Lines
test-utils/src/lib.rs 96.66% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3318   +/-   ##
=======================================
  Coverage   90.50%   90.51%           
=======================================
  Files         255      255           
  Lines       91199    91213   +14     
  Branches    91199    91213   +14     
=======================================
+ Hits        82543    82558   +15     
  Misses       5642     5642           
+ Partials     3014     3013    -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

This PR wires adaptive_metadata_enabled into the Remove projection and correctly nulls deletionTimestamp under adaptiveMetadata (AMT), which is the one obligation it fully implements. Feature detection via is_feature_enabled(AdaptiveMetadataPreview) is sound, and both the parameterized unit test and the new integration test cover the deletionTimestamp branch well. The gap is that the PR adds two more "must" invariants to the Remove doc comments that the code does not enforce, and public write paths can produce Remove actions that violate them under AMT.

Summary

The deletionTimestamp change is correct and well tested, but the PR documents extendedFileMetadata and stats as hard AMT invariants that the code does not enforce, and public scan/remove paths can emit Remove actions that violate them. Either enforce those invariants or soften the doc claims to match actual behavior before merge.


Automated review - workflow run

};
// Note: The Delta protocol requires `partitionValues`, `size`, and `tags` when
// `extendedFileMetadata` is true. We require only `partitionValues` and `size` to match Spark.
// Under adaptiveMetadata both are guaranteed present

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Blocker1 extendedFileMetadata is not forced true under adaptiveMetadata. The new doc on Remove::extended_file_metadata says "Must be true when adaptiveMetadata is enabled", but build_remove_struct_patch computes it as the same presence predicate (size is_not_null AND partitionValues is_not_null) for both paths; adaptive_metadata_enabled only affects deletionTimestamp. Commit validation requires size but not partitionValues, so an AMT remove with null partitionValues emits extendedFileMetadata=false, silently violating the RFC. The comment "Under adaptiveMetadata both are guaranteed present" is an unchecked assumption (and lacks a trailing period). Raised by: delta-protocol-reviewer, maintainer-claude-reviewer, architecture-reviewer, docs-reviewer, test-coverage-reviewer, maintainer-codex-reviewer. Suggested fix: under adaptive_metadata_enabled, validate size and partitionValues are present and emit lit(true) for extendedFileMetadata (mirroring the deletionTimestamp handling), or reword the doc/comment to describe the presence-predicate behavior instead of asserting a hard invariant.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

seems worth fixing?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is determined by the writer:

// Note: The Delta protocol requires `partitionValues`, `size`, and `tags` when
// `extendedFileMetadata` is true. We require only `partitionValues` and `size` to match Spark.
let extended_file_metadata = Predicate::and_from([
col!(SIZE_NAME).is_not_null(),
col!(FILE_CONSTANT_VALUES_NAME, PARTITION_VALUES_NAME).is_not_null(),
]);

Comment thread kernel/src/actions/mod.rs
/// Contains [statistics] (e.g., count, min/max values for columns) about the data in this
/// logical file encoded as a JSON string.
///
/// Must be set when adaptiveMetadata is enabled on the table.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Blocker2 stats "Must be set when adaptiveMetadata is enabled" is documented but not enforced. build_remove_struct_patch only passes stats through or coalesces with stats_parsed, so a null input stays null. requires_stats_num_records covers only IcebergCompatV3, which AMT does not pull in, and remove validation checks only path and size. A caller can scan with StatsOptions::none() and feed that to remove_files, producing an AMT Remove with null stats that violates the documented invariant; the new integration test never asserts stats. Raised by: delta-protocol-reviewer, maintainer-claude-reviewer, docs-reviewer, test-coverage-reviewer. Suggested fix: enforce non-null stats for AMT removes (e.g. extend the remove validation path) and add a negative test, or soften the doc claim to match actual behavior.

Comment thread test-utils/src/lib.rs Outdated
// adaptiveMetadata requires column mapping in `id` mode plus RowTracking, DomainMetadata,
// DeletionVectors, and InCommitTimestamp. Auto-enable them (mirroring the ReaderWriter features
// into both lists) so callers can pass just `adaptiveMetadata-preview` and get a loadable
// table.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit1 create_table is accreting per-feature dependency blocks: this is the second hand-written "feature implies features + config" block plus a special-case columnMapping.mode/nested-id branch on enable_adaptive_metadata. Each new gated feature adds another if-block and OR term, and it duplicates the kernel's feature-dependency graph in a test helper where it can drift. Test-only, non-blocking. Raised by: architecture-reviewer. Suggested fix: replace the if-blocks with a data-driven table mapping each feature to its required features and config entries so adding a feature is a data entry.

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown

Benchmark results: ✅ Pass

Summary: 🚀 0  ·  ✅ 8  ·  ☑️ 6  ·  🚧 1  ·  ❌ 0

Per-benchmark results (15 rows)
Test Change Base PR
clustered/readMetadataLatestPredicate/serial ✅ 1.00x 103.0±1.78ms 103.2±2.14ms
crcLatest/snapshotLatest ✅ 1.02x faster 10.7±0.37ms 10.5±0.45ms
crcMissing/snapshotLatest ✅ 1.01x faster 25.6±0.64ms 25.4±0.94ms
crcSlightlyStale/snapshotLatest ☑️ 1.02x slower 11.5±0.34ms 11.7±0.31ms
crcVeryStale/snapshotLatest ☑️ 1.01x slower 17.6±0.64ms 17.8±0.46ms
partitioned/readMetadataLatestPredicate/serial ☑️ 1.01x slower 59.2±3.49ms 59.5±2.40ms
v1Checkpoint/readMetadataLatest/serial ☑️ 1.02x slower 12.9±0.18ms 13.1±0.36ms
v1Checkpoint/snapshotLatest ✅ 1.02x faster 847.5±38.71µs 834.7±36.98µs
v2Checkpoint/readMetadataLatest/parallel2 ✅ 1.01x faster 10.4±0.49ms 10.3±0.51ms
v2Checkpoint/readMetadataLatest/serial ☑️ 1.01x slower 15.0±0.21ms 15.2±0.23ms
v2Checkpoint/snapshotLatest ☑️ 1.01x slower 844.1±32.71µs 853.7±38.97µs
wideSchemaJsonStats/readMetadataLatestPredicate/serial ✅ 1.00x 80.6±3.27ms 80.2±2.40ms
wideSchemaJsonStats/snapshotLatest ✅ 1.00x 2.4±0.05ms 2.4±0.04ms
wideSchemaStructStats/readMetadataLatestPredicate/serial 🚧 1.10x slower 34.0±1.01ms 37.5±1.19ms
wideSchemaStructStats/snapshotLatest ✅ 1.00x 2.3±0.04ms 2.3±0.05ms

Legend: 🚀 ≥1.15x faster  · ✅ faster or unchanged  · ☑️ ≤1.03x slower  · 🚧 1.03x-1.15x slower  · ❌ ≥1.15x slower
Commit: c4b96c0 · Trigger: auto-push · Tags: base · Updated: 2026-09-17 14:49 PDT

Comment thread kernel/src/actions/mod.rs Outdated
pub(crate) data_change: bool,

/// When true the fields `partition_values`, `size`, and `tags` are present
/// When true, the fields `partition_values`, `size`, and `tags` are present

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think tags was removed from the RFC

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right! Thanks!

Image

let engine = Arc::new(engine);
let schema = schema_ref! { nullable "number": INTEGER };

// `test_utils::create_table` auto-enables the adaptiveMetadata dependency features and column

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: seems like needless detail?

@Fokko Fokko Sep 16, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, I agree. I've cleaned it up

/// `test_remove_files_adds_expected_entries` covers the timestamped, conditionally-extended shape.
#[cfg(feature = "adaptive-metadata-in-dev")]
#[tokio::test]
async fn remove_on_adaptive_metadata_table_nulls_deletion_timestamp_and_forces_extended_metadata(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: this method is 90 lines long, I wonder if there are sensible places that we could add helpers for to make the core test more compact?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'm afraid the end-to-end tests are a bit longer by nature. The test above this one is over 160 lines long. We repeat a pattern multiple times where we create a temp dir, which we can move to a helper. Are you okay with doing that in a separate PR so we can keep the PRs small? I can follow up directly after this one goes in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

yeah separate PR is fine if we can clean it up.

Comment thread test-utils/src/lib.rs
// DeletionVectors, and InCommitTimestamp. Auto-enable them (mirroring the ReaderWriter features
// into both lists) so callers can pass just `adaptiveMetadata-preview` and get a loadable
// table.
let enable_adaptive_metadata = reader_features.contains(&"adaptiveMetadata-preview")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should this be a helper?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think this mimmics the pattern above, but happy to pull it into a private helper.

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

The deletionTimestamp change is correct: build_remove_struct_patch emits a null literal under adaptiveMetadata and a commit-timestamp literal otherwise, and both the parameterized unit test and the new integration test cover it. The problem in this PR is an unrelated content-tree schema change that breaks an existing contract test and diverges from the RFC.

The three AMT Remove-invariant items (extendedFileMetadata and stats documented as "must" but not enforced, and the test-utils feature-dependency accretion) were already raised against this same head SHA by the previous review, and the code behavior is unchanged, so they are not re-filed here. They remain unresolved and should still be addressed before merge.

Summary

The deletionTimestamp handling under adaptiveMetadata is correct and well tested. The blocking problem is the spec_id field-id change to 502, which breaks the existing content-entry schema-contract test and diverges from the RFC's assignment of 141; revert it or justify it against an authoritative revision and update the test. The new TrackingInfo field id 160 is unverifiable against the spec and has no user yet. Both content-tree edits are unrelated to this PR's Remove-action scope. The previously reported AMT extendedFileMetadata/stats doc-vs-code gaps are unchanged at this head SHA and still need resolution.


Automated review - workflow run

Comment thread kernel/src/content_tree/mod.rs Outdated

/// ID of partition spec used to write manifest or data/delete files.
#[field_id = 141]
#[field_id = 502]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Blocker1 spec_id field id is changed from 141 to 502, but the schema-contract test content_tree_node_entry_schema_field_contract (line 368) still asserts (PARTITION_SPEC_ID, Some(141), false) and compares the generated Parquet field id, so it fails with field id mismatch for specId. The module is gated by adaptive-metadata-in-dev, which cargo test --all-features (the pre-push gate) enables. Separately, the Iceberg-v4-metadata RFC assigns spec_id field id 141; 502 does not appear there (it is Iceberg's manifest-list partition_spec_id), so since readers resolve by field id this breaks interop. This change is also unrelated to the Remove-action subject of the PR. Raised by: maintainer-claude-reviewer, maintainer-codex-reviewer, delta-protocol-reviewer, test-coverage-reviewer, architecture-reviewer. Suggested fix: revert to #[field_id = 141]; if a newer authoritative RFC reassigns it to 502, cite that revision and update the contract test to Some(502) in the same change.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This was actually a discrapency in the draft V4 spec

Comment thread kernel/src/content_tree/mod.rs Outdated

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

No blocking issues. The core change is correct: build_remove_struct_patch emits a null deletionTimestamp literal under adaptiveMetadata and a commit-timestamp literal otherwise, which matches the iceberg-v4-metadata RFC Remove-file requirement. The parameterized unit test and the new end-to-end integration test both cover the null and timestamped branches, and the test-utils AMT dependency auto-enable (columnMapping id mode plus rowTracking, domainMetadata, deletionVectors, inCommitTimestamp, with the correct reader/writer split) matches the RFC and the kernel's enforced feature requirements.

Summary

The adaptiveMetadata deletionTimestamp handling is correct and well covered by both unit and integration tests, and the test-utils feature wiring is accurate. The only new item is a minor test-assertion tightening. Note that the previously reported extendedFileMetadata and stats doc-vs-enforcement gaps are unchanged at this head SHA and remain unresolved; they are not re-filed here.


Automated review - workflow run

let removes = read_actions_from_commit(&table_url, version, "remove")?;
assert_eq!(removes.len(), 1, "expected exactly one remove action");
let remove = &removes[0];
assert!(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nit1 The deletionTimestamp assertion uses remove.get("deletionTimestamp").is_none_or(|v| v.is_null()), which also passes if the field is absent entirely. Since the invariant is that an explicit null is emitted, a regression that dropped the field rather than serializing null would slip through. Raised by: test-coverage-reviewer. Suggested fix: assert the key is present and null, e.g. assert!(remove["deletionTimestamp"].is_null(), ...), after confirming the committed action serializes null_lit as an explicit null.

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

No new blocking issues at this head SHA.

The core change is correct. Under adaptiveMetadata, build_remove_struct_patch emits null_lit(DataType::LONG) for deletionTimestamp and a commit-timestamp literal otherwise, which matches the iceberg-v4-metadata RFC Remove-file requirement. Feature detection via is_feature_enabled(&TableFeature::AdaptiveMetadataPreview) is sound, the make_eval closure's explicit DeltaResult return type is a no-op clarity change, and the test-utils AMT dependency auto-enable (columnMapping id mode plus rowTracking, domainMetadata, deletionVectors, inCommitTimestamp with the correct reader/writer split) matches the RFC and the kernel's feature_requirements. The parameterized unit test and the new integration test both exercise the null and timestamped branches.

The reviewers reconfirmed the earlier doc-vs-enforcement gaps: the newly documented extendedFileMetadata "must be true" and stats "must be set" AMT invariants are not enforced by build_remove_struct_patch or the commit path, the inline comment "Under adaptiveMetadata both are guaranteed present" states an unchecked assumption, and the integration test's deletionTimestamp assertion (is_none_or(|v| v.is_null())) also passes if the field is dropped entirely. These match findings already raised against this same head SHA in the supplied review history, and the code behavior is unchanged, so they are not re-filed here. They remain unresolved and should still be addressed before merge, either by enforcing the invariants under adaptive_metadata_enabled or by softening the doc and comment wording to match the presence-predicate behavior.

Summary

The deletionTimestamp handling under adaptiveMetadata is correct and covered by both unit and integration tests, and the test-utils feature wiring is accurate. No new blocking issues at this head SHA. The previously reported extendedFileMetadata/stats doc-vs-enforcement gaps and the weak deletionTimestamp test assertion are unchanged and not re-filed, but they still need resolution before merge. All six reviewers completed; no reduced coverage.


Automated review - workflow run

@Fokko
Fokko requested a review from kyli87 September 17, 2026 09:58

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

No new blocking issues at this head SHA.

The core change is correct and RFC-conformant. Under adaptiveMetadata, build_remove_struct_patch emits null_lit(DataType::LONG) for deletionTimestamp and a commit-timestamp literal otherwise, which matches the iceberg-v4-metadata RFC Remove-file requirement. Feature detection via is_feature_enabled(&TableFeature::AdaptiveMetadataPreview) is sound, the make_eval explicit DeltaResult<_> return type is a clarity-only change, and the test-utils AMT dependency auto-enable (columnMapping id mode plus rowTracking, domainMetadata, deletionVectors, inCommitTimestamp with the correct reader/writer split) mirrors the kernel's feature_requirements. The parameterized unit test and the new integration test both exercise the null and timestamped branches.

The reviewers reconfirmed the previously reported gaps at this same head SHA: the documented extendedFileMetadata "must be true" and stats "must be set" AMT invariants are not enforced by build_remove_struct_patch or the commit path (both remain the presence predicate / pass-through for both paths), the inline comment "Under adaptiveMetadata both are guaranteed present" states an unchecked assumption, and the integration test's deletionTimestamp assertion (is_none_or(|v| v.is_null())) also passes if the field is dropped entirely. These match findings already raised against this head SHA in the supplied review history and the code behavior is unchanged, so they are not re-filed here. They remain unresolved and should be closed out before merge, either by enforcing the invariants under adaptive_metadata_enabled or by softening the doc and comment wording to match the presence-predicate behavior.

Summary

The deletionTimestamp handling under adaptiveMetadata is correct, RFC-compliant, and covered by both unit and integration tests, and the test-utils feature wiring is accurate. No new blocking issues at this head SHA. The previously reported extendedFileMetadata/stats doc-vs-enforcement gaps, the unchecked inline comment, and the weak deletionTimestamp test assertion are unchanged and not re-filed, but they still need resolution before merge. All six reviewers completed; no reduced coverage.


Automated review - workflow run

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

No blocking issues.

The core change is correct and matches the iceberg-v4-metadata RFC Remove-file requirement. Under adaptiveMetadata, build_remove_struct_patch emits null_lit(DataType::LONG) for deletionTimestamp and lit(commit_timestamp) otherwise. Feature detection via is_feature_enabled(&TableFeature::AdaptiveMetadataPreview) is sound, the flag is computed once in generate_remove_actions and threaded as a plain bool into a config-free builder, and the literal type matches the Option<i64> field. The test-utils enable_adaptive_metadata_dependencies wiring mirrors the kernel's feature_requirements: the ReaderWriter deps (columnMapping, deletionVectors) plus adaptiveMetadata-preview go into both lists, and the writer-only deps (rowTracking, domainMetadata, inCommitTimestamp) into the writer list only. The parameterized unit test and the new integration test exercise both the null and timestamped branches.

The reviewers reconfirmed several pre-existing gaps at this same head SHA, all with unchanged code behavior: the documented extendedFileMetadata "must be true" and stats "must be set" AMT invariants are not enforced by build_remove_struct_patch (both stay the presence predicate / pass-through on both paths), the inline comment "Under adaptiveMetadata both are guaranteed present" states an unchecked assumption, the integration test's is_none_or(|v| v.is_null()) assertion also passes if the field is dropped entirely, and the test-utils helper hand-transcribes the kernel's feature-dependency graph rather than deriving it. These match findings already raised against this head SHA in the supplied review history, so they are not re-filed. They remain unresolved and should be closed before merge, either by enforcing the invariants under adaptive_metadata_enabled or by softening the doc and comment wording to match the presence-predicate behavior.


Automated review - workflow run

@Fokko
Fokko added this pull request to the merge queue Sep 17, 2026
@Fokko
Fokko removed this pull request from the merge queue due to a manual request Sep 17, 2026

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

Summary

The deletionTimestamp logic is correct and RFC-conformant: build_remove_struct_patch emits null_lit(DataType::LONG) under adaptiveMetadata and lit(commit_timestamp) otherwise, feature detection via is_feature_enabled(&TableFeature::AdaptiveMetadataPreview) is sound, and both the parameterized unit test and the new integration test cover the two branches. The test-utils dependency wiring matches the kernel feature requirements. The one blocker is a duplicate null_lit import that fails to compile under adaptive-metadata-in-dev/--all-features; fixing the import is a one-line change. The previously reported doc-vs-enforcement gaps (extendedFileMetadata/stats documented as required but not enforced), the "guaranteed present" inline comment, and the permissive is_none_or deletionTimestamp assertion are unchanged at this head SHA and are not re-filed, but they remain open. All six reviewers and the disprove gate completed; no reduced coverage.


Automated review - workflow run

Comment thread kernel/src/transaction/mod.rs

@github-actions github-actions 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.

AI Review (draft - human review required)

Show review

No blocking issues.

The core change is correct and matches the iceberg-v4-metadata RFC Remove-file requirement. Under adaptiveMetadata, build_remove_struct_patch emits null_lit(DataType::LONG) for deletionTimestamp and lit(commit_timestamp) otherwise; the literal type matches the Option<i64> field. Feature detection via is_feature_enabled(&TableFeature::AdaptiveMetadataPreview) is sound, computed once in generate_remove_actions and threaded as a plain bool into the config-free builder. The previously reported duplicate null_lit import is resolved at this head SHA: null_lit now appears only in the unconditional grouped import and is used on the always-compiled path, so both the default and adaptive-metadata-in-dev / --all-features builds compile cleanly. The test-utils enable_adaptive_metadata_dependencies helper mirrors the kernel's real ADAPTIVE_METADATA_PREVIEW_INFO.feature_requirements (ReaderWriter deps in both lists, writer-only deps in the writer list). The parameterized unit test and the new integration test exercise the null and timestamped branches.

The reviewers reconfirmed several pre-existing items at this unchanged head SHA: the documented extendedFileMetadata "must be true" and stats "must be set" invariants are not enforced by build_remove_struct_patch (both remain the presence predicate / pass-through on both paths), the inline comment "Under adaptiveMetadata both are guaranteed present" states an unchecked assumption, and the integration test's deletionTimestamp assertion also passes if the field is absent. These match findings already raised against this same head SHA in the supplied review history, so they are not re-filed. The test-coverage reviewer also noted that, because the kernel omits null Remove fields from commit JSON (as the sibling backReference test documents), the current is_none_or(|v| v.is_null()) assertion is appropriate and should not be tightened to require an explicit present-and-null key. All six reviewers completed; no reduced coverage.


Automated review - workflow run

@Fokko
Fokko enabled auto-merge September 17, 2026 21:51
@Fokko
Fokko added this pull request to the merge queue Sep 17, 2026
Merged via the queue into delta-io:main with commit c457674 Sep 17, 2026
40 checks passed
@Fokko
Fokko deleted the fd-remove branch September 17, 2026 22:05
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