From 83cf0f280c8791a714fb5592d5db83405648ebde Mon Sep 17 00:00:00 2001 From: swackhamer Date: Mon, 10 Aug 2026 13:55:33 -0500 Subject: [PATCH 1/4] fix(djvu): wire 1 missing tags (via gpt-5.6-sol) Format: DJVU Tag: DjVu:Note Sample: /tmp/oxidex-exiftool-cache/combined-samples/DjVu.djvu Exiftool-Value: 'Must escape double quotes (") and backslashes (\\)' Oxidex-Value: 'Must escape double quotes (") and backslashes (\\)' Verified: recheck-pass gaps=1->0 Worker: tail-9 --- src/parsers/image/djvu.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/parsers/image/djvu.rs b/src/parsers/image/djvu.rs index 9e514f01d..613cf903d 100644 --- a/src/parsers/image/djvu.rs +++ b/src/parsers/image/djvu.rs @@ -177,7 +177,11 @@ fn metadata_from_expression(expression: Expression, metadata: &mut MetadataMap) "DjVu:Trapped".to_string(), TagValue::new_string(value.trim_start_matches('/').to_string()), ), - "note" | "Subject" | "Keywords" | "Creator" | "Producer" => { + "note" => metadata.insert( + "DjVu:Note".to_string(), + TagValue::new_string(value.clone()), + ), + "Subject" | "Keywords" | "Creator" | "Producer" => { metadata.insert(format!("DjVu:{name}"), TagValue::new_string(value.clone())) } _ => None, From 5315ffd6fe3f1c907f4facddf56e5e509286fe0f Mon Sep 17 00:00:00 2001 From: swackhamer Date: Mon, 10 Aug 2026 17:05:11 -0500 Subject: [PATCH 2/4] fix(ape): wire 1 missing tags (via gpt-5.6-sol) Format: APE Tag: Composite:Duration Sample: /tmp/oxidex-exiftool-cache/combined-samples/APE.ape Exiftool-Value: '2.64 s' Oxidex-Value: '2.64 s' Perl-Ref: APE.pm Verified: recheck-pass gaps=1->0 Worker: tail-5 --- src/parsers/audio/ape.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/parsers/audio/ape.rs b/src/parsers/audio/ape.rs index d7f81fef7..0e4bcda0c 100644 --- a/src/parsers/audio/ape.rs +++ b/src/parsers/audio/ape.rs @@ -182,7 +182,7 @@ fn parse_mac_audio_header( let samples = u64::from(total_frames - 1) * u64::from(blocks_per_frame) + u64::from(final_frame_blocks); metadata.insert( - "APE:Duration".to_string(), + "Composite:Duration".to_string(), TagValue::new_string(convert_duration(samples as f64 / f64::from(sample_rate))), ); } @@ -429,6 +429,7 @@ mod tests { metadata.get("APE:SampleRate").unwrap().as_integer(), Some(44100) ); + assert_eq!(text(&metadata, "Composite:Duration"), "2.64 s"); } #[test] From ced66649eec715bfd0ce16feddda615bcb7c52ac Mon Sep 17 00:00:00 2001 From: swackhamer Date: Mon, 10 Aug 2026 18:35:50 -0500 Subject: [PATCH 3/4] fix(bpg): wire 1 missing tags (via gpt-5.6-sol) Format: BPG Tag: XMP:ComponentsConfiguration Sample: /tmp/oxidex-exiftool-cache/combined-samples/BPG.bpg Exiftool-Value: 'Y, Cb, Cr, -' Oxidex-Value: 'Y, Cb, Cr, -' Perl-Ref: Exif.pm Verified: recheck-pass gaps=1->0 Worker: xmp-1 --- src/parsers/image/embedded.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/parsers/image/embedded.rs b/src/parsers/image/embedded.rs index c7f695d12..205504770 100644 --- a/src/parsers/image/embedded.rs +++ b/src/parsers/image/embedded.rs @@ -14,7 +14,7 @@ use crate::core::{MetadataMap, TagValue}; use crate::io::buffered_reader::BufferedReader; use crate::io::{ByteOrder as IoByteOrder, EndianReader}; use crate::parsers::tiff::ifd_parser::{ByteOrder, parse_ifd}; -use crate::parsers::xmp::rdf_parser::parse_xmp; +use crate::parsers::xmp::rdf_parser::{XmpValue, parse_xmp_typed}; use crate::tag_db::lookup_tag_name; /// EXIF sub-IFD pointer (`ExifOffset`). @@ -127,11 +127,17 @@ pub fn parse_embedded_xmp(xmp_data: &[u8], metadata: &mut MetadataMap) -> bool { if std::str::from_utf8(xmp_data).is_err() { return false; } - match parse_xmp(xmp_data) { + match parse_xmp_typed(xmp_data) { Ok(tags) => { let found = !tags.is_empty(); for (name, value) in tags { - metadata.insert(name, TagValue::new_string(value)); + let value = match value { + XmpValue::Scalar(value) => TagValue::new_string(value), + XmpValue::List(values) => TagValue::Array( + values.into_iter().map(TagValue::new_string).collect(), + ), + }; + metadata.insert(name, value); } found } From b9e7b6b5c90413590ddba731d74498729458892e Mon Sep 17 00:00:00 2001 From: swackhamer Date: Tue, 11 Aug 2026 02:14:03 -0500 Subject: [PATCH 4/4] style: cargo fmt --all (sweep publish) Worker-authored Rust reaches this branch semantically validated but never style-checked: validate_fix_commit.py, the per-commit merger check and the post-merge recheck all assert behaviour (gap deltas, no duplicate emissions, no unexplained oxidex-only keys) and none of them look at formatting. CI's "Lint & Audit" job runs `cargo fmt --all -- --check`, so an unformatted sweep branch fails CI by construction. Measured on PR #124 (branch sweep/tags-2026-07-26-1, the first sweep PR ever opened): CI run 30186389305 -- "Build & Test" success, "Lint & Audit" failure, and the failing step is literally `Run cargo fmt --all -- --check`. Kept as a separate commit so the tag-fix diffs stay readable. --- src/parsers/image/djvu.rs | 5 +---- src/parsers/image/embedded.rs | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/parsers/image/djvu.rs b/src/parsers/image/djvu.rs index 613cf903d..216895601 100644 --- a/src/parsers/image/djvu.rs +++ b/src/parsers/image/djvu.rs @@ -177,10 +177,7 @@ fn metadata_from_expression(expression: Expression, metadata: &mut MetadataMap) "DjVu:Trapped".to_string(), TagValue::new_string(value.trim_start_matches('/').to_string()), ), - "note" => metadata.insert( - "DjVu:Note".to_string(), - TagValue::new_string(value.clone()), - ), + "note" => metadata.insert("DjVu:Note".to_string(), TagValue::new_string(value.clone())), "Subject" | "Keywords" | "Creator" | "Producer" => { metadata.insert(format!("DjVu:{name}"), TagValue::new_string(value.clone())) } diff --git a/src/parsers/image/embedded.rs b/src/parsers/image/embedded.rs index 205504770..9ce9d9b82 100644 --- a/src/parsers/image/embedded.rs +++ b/src/parsers/image/embedded.rs @@ -133,9 +133,9 @@ pub fn parse_embedded_xmp(xmp_data: &[u8], metadata: &mut MetadataMap) -> bool { for (name, value) in tags { let value = match value { XmpValue::Scalar(value) => TagValue::new_string(value), - XmpValue::List(values) => TagValue::Array( - values.into_iter().map(TagValue::new_string).collect(), - ), + XmpValue::List(values) => { + TagValue::Array(values.into_iter().map(TagValue::new_string).collect()) + } }; metadata.insert(name, value); }