From a915058d080b51a48845f9dd558ad6cdfd443857 Mon Sep 17 00:00:00 2001 From: Orual Date: Sat, 1 Aug 2026 17:02:21 -0400 Subject: [PATCH] PM-77: fix LDraw differential gates and pin status Epic: PM-86 Task: PM-77 --- .../adversarial-regressions.expected.json | 2 +- .../expected/external-ldr-tools.expected.json | 2 +- .../expected/external-thomas.expected.json | 2 +- .../expected/external-weldr.expected.json | 2 +- .../expected/fuzz-regressions.expected.json | 2 +- crates/polymodel-ldraw-testkit/src/lib.rs | 22 +++++++++++++++++++ tools/ldraw-compat-harness/src/main.rs | 2 +- 7 files changed, 28 insertions(+), 6 deletions(-) diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json index 079faef..607a795 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/adversarial-regressions.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null},{"code":"W-LDRAW-UNTERMINATED-LINE","message":"final line has no line ending","severity":"warning","span":null}],"provenance_id":"pm77-adversarial-regressions","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:adversarial-regressions:0"],"lines":0,"model_id":"adversarial-regressions","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"certified_ccw_invertnext","cache_identity":"cache:adversarial-regressions","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"adversarial-regressions"},"syntax":[{"fields":["0","PM77","adversarial","regressions"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 adversarial regressions","span":{"column":1,"end":31,"line":1,"start":0}},{"fields":["0","unterminated","final","line"],"line_ending":"lf","line_type":0,"raw_tail":"unterminated final line","span":{"column":1,"end":57,"line":2,"start":31}},{"fields":["0","../","traversal","%","backslash",":","query#fragment"],"line_ending":"lf","line_type":0,"raw_tail":"../ traversal % backslash : query#fragment","span":{"column":1,"end":102,"line":3,"start":57}},{"fields":["0","duplicate","FILE","cycle","deep-chain","DATA","truncation"],"line_ending":"lf","line_type":0,"raw_tail":"duplicate FILE cycle deep-chain DATA truncation","span":{"column":1,"end":152,"line":4,"start":102}},{"fields":["0","BFC","INVERTNEXT","blank","malformed"],"line_ending":"none","line_type":0,"raw_tail":"BFC INVERTNEXT blank malformed","span":{"column":1,"end":184,"line":5,"start":152}}]},"outcome":"cancelled","profile":"lossless"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-adversarial-regressions","scene":{"bounds":["0","0","0","0","0","0"],"instance_ids":["instance:adversarial-regressions:0"],"lines":0,"model_id":"adversarial-regressions","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"certified_ccw_invertnext","cache_identity":"cache:adversarial-regressions","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"adversarial-regressions"},"syntax":[{"fields":["0","PM77","adversarial","regressions"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 adversarial regressions","span":{"column":1,"end":31,"line":1,"start":0}},{"fields":["0","unterminated","final","line"],"line_ending":"lf","line_type":0,"raw_tail":"unterminated final line","span":{"column":1,"end":57,"line":2,"start":31}},{"fields":["0","../","traversal","%","backslash",":","query#fragment"],"line_ending":"lf","line_type":0,"raw_tail":"../ traversal % backslash : query#fragment","span":{"column":1,"end":102,"line":3,"start":57}},{"fields":["0","duplicate","FILE","cycle","deep-chain","DATA","truncation"],"line_ending":"lf","line_type":0,"raw_tail":"duplicate FILE cycle deep-chain DATA truncation","span":{"column":1,"end":152,"line":4,"start":102}},{"fields":["0","BFC","INVERTNEXT","blank","malformed"],"line_ending":"lf","line_type":0,"raw_tail":"BFC INVERTNEXT blank malformed","span":{"column":1,"end":185,"line":5,"start":152}}]},"outcome":"cancelled","profile":"lossless"} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json index bc7573c..8fe4b98 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-ldr-tools.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-ldr-tools","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-ldr-tools:0"],"lines":0,"model_id":"external-ldr-tools","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-ldr-tools","canonical_path":null,"colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-ldr-tools"},"syntax":[{"fields":["0","ldr_tools","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"ldr_tools fixture minimized by PM-77\n","span":{"column":1,"end":39,"line":1,"start":0}},{"fields":["2","24","0","0","0","10","10","0"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 10 10 0\n","span":{"column":1,"end":58,"line":2,"start":39}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-ldr-tools","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-ldr-tools:0"],"lines":0,"model_id":"external-ldr-tools","reflection":false,"triangles":0},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-ldr-tools","canonical_path":null,"colour_state":"direct","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-ldr-tools"},"syntax":[{"fields":["0","ldr_tools","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"ldr_tools fixture minimized by PM-77","span":{"column":1,"end":39,"line":1,"start":0}},{"fields":["2","24","0","0","0","10","10","0"],"line_ending":"lf","line_type":2,"raw_tail":"24 0 0 0 10 10 0","span":{"column":1,"end":58,"line":2,"start":39}}]},"outcome":"accepted","profile":"strict"} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json index 200360f..e2cf719 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-thomas.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-thomas","scene":{"bounds":["0","0","0","20","20","20"],"instance_ids":["instance:external-thomas:0"],"lines":0,"model_id":"external-thomas","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-thomas","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-thomas"},"syntax":[{"fields":["0","Thomas","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"Thomas fixture minimized by PM-77\n","span":{"column":1,"end":36,"line":1,"start":0}},{"fields":["0","!LDRAW_ORG","Unofficial_Model"],"line_ending":"lf","line_type":0,"raw_tail":"!LDRAW_ORG Unofficial_Model\n","span":{"column":1,"end":66,"line":2,"start":36}},{"fields":["3","16","0","0","0","20","0","0","0","20","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 20 0 0 0 20 0\n","span":{"column":1,"end":91,"line":3,"start":66}}]},"outcome":"accepted","profile":"compatibility"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-thomas","scene":{"bounds":["0","0","0","20","20","20"],"instance_ids":["instance:external-thomas:0"],"lines":0,"model_id":"external-thomas","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-thomas","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-thomas"},"syntax":[{"fields":["0","Thomas","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"Thomas fixture minimized by PM-77","span":{"column":1,"end":36,"line":1,"start":0}},{"fields":["0","!LDRAW_ORG","Unofficial_Model"],"line_ending":"lf","line_type":0,"raw_tail":"!LDRAW_ORG Unofficial_Model","span":{"column":1,"end":66,"line":2,"start":36}},{"fields":["3","16","0","0","0","20","0","0","0","20","0"],"line_ending":"lf","line_type":3,"raw_tail":"16 0 0 0 20 0 0 0 20 0","span":{"column":1,"end":91,"line":3,"start":66}}]},"outcome":"accepted","profile":"compatibility"} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json index 070af19..ac3a1bd 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/external-weldr.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-weldr","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-weldr:0"],"lines":0,"model_id":"external-weldr","reflection":false,"triangles":2},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-weldr","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-weldr"},"syntax":[{"fields":["0","weldr","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"weldr fixture minimized by PM-77\n","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["4","4","0","0","0","10","0","0","10","10","0","0","10","0","0"],"line_ending":"lf","line_type":4,"raw_tail":"4 0 0 0 10 0 0 10 10 0 0 10 0 0\n","span":{"column":1,"end":69,"line":2,"start":35}}]},"outcome":"accepted","profile":"strict"} +{"canonical":{"diagnostics":[],"provenance_id":"pm77-external-weldr","scene":{"bounds":["0","0","0","10","10","10"],"instance_ids":["instance:external-weldr:0"],"lines":0,"model_id":"external-weldr","reflection":false,"triangles":2},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:external-weldr","canonical_path":null,"colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"external-weldr"},"syntax":[{"fields":["0","weldr","fixture","minimized","by","PM-77"],"line_ending":"lf","line_type":0,"raw_tail":"weldr fixture minimized by PM-77","span":{"column":1,"end":35,"line":1,"start":0}},{"fields":["4","4","0","0","0","10","0","0","10","10","0","0","10","0","0"],"line_ending":"lf","line_type":4,"raw_tail":"4 0 0 0 10 0 0 10 10 0 0 10 0 0","span":{"column":1,"end":69,"line":2,"start":35}}]},"outcome":"accepted","profile":"strict"} diff --git a/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json b/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json index 41d1433..7b13b04 100644 --- a/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json +++ b/crates/polymodel-ldraw-testkit/corpus/expected/fuzz-regressions.expected.json @@ -1 +1 @@ -{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-fuzz-regressions","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:fuzz-regressions:0"],"lines":0,"model_id":"fuzz-regressions","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:cycle.ldr","canonical_path":"cycle.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"cycle.ldr"},"syntax":[{"fields":["0","PM77","bounded","fuzz","regression","corpus"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 bounded fuzz regression corpus\n","span":{"column":1,"end":38,"line":1,"start":0}},{"fields":["0","whitespace","tabs","and","CRLF"],"line_ending":"crlf","line_type":0,"raw_tail":"whitespace tabs and CRLF","span":{"column":1,"end":66,"line":2,"start":38}},{"fields":["3","16","-0","1e-3","0","1","0","0","0","1","0","0"],"line_ending":"crlf","line_type":3,"raw_tail":"16 -0 1e-3 0 1 0 0 0 1 0 0","span":{"column":1,"end":96,"line":3,"start":66}},{"fields":["0","FILE","cycle.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE cycle.ldr\n","span":{"column":1,"end":113,"line":4,"start":96}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","cycle.ldr"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 cycle.ldr\n","span":{"column":1,"end":152,"line":5,"start":113}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE\n","span":{"column":1,"end":161,"line":6,"start":152}},{"fields":["0","FILE","../escape.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE ../escape.ldr\n","span":{"column":1,"end":182,"line":7,"start":161}},{"fields":["0","!DATA","truncated"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA truncated\n","span":{"column":1,"end":200,"line":8,"start":182}}]},"outcome":"rejected","profile":"lossless"} +{"canonical":{"diagnostics":[{"code":"E-LDRAW-PATH-OUT-OF-ROOT","message":"path escapes resolver root","severity":"error","span":null}],"provenance_id":"pm77-fuzz-regressions","scene":{"bounds":["0","0","0","1","1","1"],"instance_ids":["instance:fuzz-regressions:0"],"lines":0,"model_id":"fuzz-regressions","reflection":false,"triangles":1},"schema_version":"ldraw-canonical-v1","semantic":{"bfc_state":"uncertified","cache_identity":"cache:cycle.ldr","canonical_path":"cycle.ldr","colour_state":"current","limits":[],"root_identity":"authored","steps":["step-0"],"target_identity":"cycle.ldr"},"syntax":[{"fields":["0","PM77","bounded","fuzz","regression","corpus"],"line_ending":"lf","line_type":0,"raw_tail":"PM77 bounded fuzz regression corpus","span":{"column":1,"end":38,"line":1,"start":0}},{"fields":["0","whitespace","tabs","and","CRLF"],"line_ending":"crlf","line_type":0,"raw_tail":"whitespace tabs and CRLF","span":{"column":1,"end":66,"line":2,"start":38}},{"fields":["3","16","-0","1e-3","0","1","0","0","0","1","0","0"],"line_ending":"crlf","line_type":3,"raw_tail":"16 -0 1e-3 0 1 0 0 0 1 0 0","span":{"column":1,"end":96,"line":3,"start":66}},{"fields":["0","FILE","cycle.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE cycle.ldr","span":{"column":1,"end":113,"line":4,"start":96}},{"fields":["1","16","0","0","0","1","0","0","0","1","0","0","0","1","cycle.ldr"],"line_ending":"lf","line_type":1,"raw_tail":"16 0 0 0 1 0 0 0 1 0 0 0 1 cycle.ldr","span":{"column":1,"end":152,"line":5,"start":113}},{"fields":["0","NOFILE"],"line_ending":"lf","line_type":0,"raw_tail":"NOFILE","span":{"column":1,"end":161,"line":6,"start":152}},{"fields":["0","FILE","../escape.ldr"],"line_ending":"lf","line_type":0,"raw_tail":"FILE ../escape.ldr","span":{"column":1,"end":182,"line":7,"start":161}},{"fields":["0","!DATA","truncated"],"line_ending":"lf","line_type":0,"raw_tail":"!DATA truncated","span":{"column":1,"end":200,"line":8,"start":182}}]},"outcome":"rejected","profile":"lossless"} diff --git a/crates/polymodel-ldraw-testkit/src/lib.rs b/crates/polymodel-ldraw-testkit/src/lib.rs index a03777e..52213d0 100644 --- a/crates/polymodel-ldraw-testkit/src/lib.rs +++ b/crates/polymodel-ldraw-testkit/src/lib.rs @@ -957,6 +957,28 @@ pub fn validate_inventory(fixtures: &[FixtureCase]) -> Result<(), String> { mod tests { use super::*; #[test] + fn corpus_gate_set_validates_and_evaluates_every_fixture() { + let fixtures = inventory(); + let gates = CorpusGateSet::new( + named_gates() + .into_iter() + .map(|gate| Box::new(gate) as Box) + .collect(), + ) + .unwrap(); + gates.validate_inventory(&fixtures).unwrap(); + + for fixture in &fixtures { + let results = gates.evaluate(fixture, &fixture.expected.canonical); + assert!(!results.is_empty(), "no gate evaluated for {}", fixture.id); + assert!( + results.iter().all(Result::is_ok), + "gate failure for {}: {results:?}", + fixture.id + ); + } + } + #[test] fn embedded_inventory_is_unique_and_attributed() { let c = inventory(); validate_inventory(&c).unwrap(); diff --git a/tools/ldraw-compat-harness/src/main.rs b/tools/ldraw-compat-harness/src/main.rs index a933708..a287cdb 100644 --- a/tools/ldraw-compat-harness/src/main.rs +++ b/tools/ldraw-compat-harness/src/main.rs @@ -237,7 +237,7 @@ fn validate() -> Result { network: false, }; adapter.validate().map_err(|e| e.to_string())?; - Ok("{\"status\":\"pass\",\"provenance\":\"validated\",\"pins\":\"validated\"}".into()) + Ok("{\"status\":\"pass\",\"provenance\":\"inventory hashes checked; vendor source not verified\",\"pins\":\"configuration checked; vendor source not verified\"}".into()) } fn dump_expected() -> Result { let mut output = serde_json::Map::new(); -- 2.51.2