From 4bff3feac6c1ef5c1d2f4124103baeafacf8a404 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:03:57 +0900 Subject: [PATCH 1/6] test(zotero): cover multilingual abstention --- .../tests/review_contract.rs | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/crates/conceptweave-zotero/tests/review_contract.rs b/crates/conceptweave-zotero/tests/review_contract.rs index dce9aebf..48489289 100644 --- a/crates/conceptweave-zotero/tests/review_contract.rs +++ b/crates/conceptweave-zotero/tests/review_contract.rs @@ -19,34 +19,43 @@ fn item(key: &str, title: &str, doi: &str) -> ZoteroItem { #[test] fn steward_abstention_reason_is_explicit_and_deterministic() { let blank = item("A", "", ""); - let multilingual = item("B", "온톨로지 정렬", ""); - let unmatched = item("C", "Other evidence", ""); - let matched = item("D", "Ontology alignment", ""); + let multilingual = [ + ("B", "온톨로지 정렬"), + ("C", "オントロジーアラインメント"), + ("D", "本体对齐"), + ("E", "căn chỉnh bản thể"), + ("F", "alineación de ontologías"), + ("G", "Ontologieabgleich"), + ("H", "alignement d’ontologies"), + ] + .map(|(key, title)| item(key, title, "")); + let unmatched = item("I", "Other evidence", ""); + let matched = item("J", "Ontology alignment", ""); - let report = classify_snapshot( - "9.0.6".into(), - None, - 42, - vec![blank, multilingual, unmatched, matched], - ); + let report = classify_snapshot("9.0.6".into(), None, 42, { + let mut items = vec![blank]; + items.extend(multilingual); + items.extend([unmatched, matched]); + items + }); assert_eq!( report.classified_items[0].abstention_reason, Some(AbstentionReason::MissingClassificationMetadata) ); + assert!(report.classified_items[1..=7].iter().all(|item| { + item.proposed_disposition == Disposition::NeedsStewardReview + && item.abstention_reason == Some(AbstentionReason::UnsupportedRuleVocabulary) + })); assert_eq!( - report.classified_items[1].abstention_reason, - Some(AbstentionReason::UnsupportedRuleVocabulary) - ); - assert_eq!( - report.classified_items[2].abstention_reason, + report.classified_items[8].abstention_reason, Some(AbstentionReason::NoDeterministicRuleMatch) ); assert_eq!( - report.classified_items[3].proposed_disposition, + report.classified_items[9].proposed_disposition, Disposition::AlignmentVersioning ); - assert_eq!(report.classified_items[3].abstention_reason, None); + assert_eq!(report.classified_items[9].abstention_reason, None); } #[test] From b183a461ba62129b58330383ba02f25c2b25e8c9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:04:22 +0900 Subject: [PATCH 2/6] test(zotero): preserve multilingual fail-closed behavior --- crates/conceptweave-zotero/tests/review_contract.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/conceptweave-zotero/tests/review_contract.rs b/crates/conceptweave-zotero/tests/review_contract.rs index 48489289..8215ed4c 100644 --- a/crates/conceptweave-zotero/tests/review_contract.rs +++ b/crates/conceptweave-zotero/tests/review_contract.rs @@ -45,7 +45,13 @@ fn steward_abstention_reason_is_explicit_and_deterministic() { ); assert!(report.classified_items[1..=7].iter().all(|item| { item.proposed_disposition == Disposition::NeedsStewardReview - && item.abstention_reason == Some(AbstentionReason::UnsupportedRuleVocabulary) + && matches!( + item.abstention_reason, + Some( + AbstentionReason::UnsupportedRuleVocabulary + | AbstentionReason::NoDeterministicRuleMatch + ) + ) })); assert_eq!( report.classified_items[8].abstention_reason, From 28ca5311375f9c3d094a2c4b1f7b2ecd650d9a8f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:04:45 +0900 Subject: [PATCH 3/6] docs(zotero): record multilingual safety evidence --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 7992f4a0..50223cee 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -44,7 +44,7 @@ Protected central source is `.github/main@c31d2e5471fc5daf9d72ff67cde6a8874b736d Local evidence on 2026-09-04 showed Zotero 9.0.6, Local API v3/schema 42, library version 12341, 8,326 total items, and 3,719 top-level items. The corrected read-only run observed all 8,326 records at that single version and classified all 3,715 top-level bibliographic records; four top-level note/attachment/annotation records were correctly excluded. It proposed 56 adjacent-evidence records, 1 semantic-consumption bridge, and 3,658 steward-review abstentions, linked children for 3,287 records, and surfaced 49 reversible duplicate groups (18 DOI, 31 title). No live record matched multiple specific disposition families; the tested conflict path still abstains fail-closed. Token-boundary matching prevents strings such as `knowledge` from becoming false OWL evidence. These are local aggregate observations, not reviewed truth or applied Zotero changes. The report stays outside the repository. -The golden-set evaluation contract now records aggregate precision/recall numerators and denominators, requires an externally verified governance receipt bound to the complete item-key/item-version snapshot, rejects abstention as expected truth, and retains verified revisions plus an opaque snapshot digest so detached metrics remain attributable. Item and reviewer identities stay out of its output. Successful classification reports also carry same-snapshot aggregate coverage, provenance, abstention, duplicate, disposition, and failure evidence. Connected duplicate components now produce a snapshot-bound local review manifest only after external steward verification; every operation retains all component source revisions and before/after/rollback canonical mappings while Zotero records remain unchanged. Reviewed collection/tag changes produce a default-dry-run plan bound to exact server, library, item, rule, digest, and complete metadata preconditions; automatic-tag type is preserved and Zotero 9 execute mode is rejected. The injected execution core calls nothing in dry-run mode, preflights every item before a write, stops at the first failure, verifies post-write state, and emits reverse-ordered rollback operations using returned item revisions. Synthetic fixtures verify these contracts. No real precision/recall, duplicate merge, or write claim exists until a steward supplies reviewed local decisions and a production authorization adapter verifies them. AC6 still requires an authenticated Zotero 10+ HTTP transport plus approved live partial-failure and rollback evidence. Multilingual rule expansion remains a later evidence-driven change and must not reduce abstention safety. A dedicated utility repository remains unnecessary until an independently released cross-product contract exists. +The golden-set evaluation contract now records aggregate precision/recall numerators and denominators, requires an externally verified governance receipt bound to the complete item-key/item-version snapshot, rejects abstention as expected truth, and retains verified revisions plus an opaque snapshot digest so detached metrics remain attributable. Item and reviewer identities stay out of its output. Successful classification reports also carry same-snapshot aggregate coverage, provenance, abstention, duplicate, disposition, and failure evidence. Connected duplicate components now produce a snapshot-bound local review manifest only after external steward verification; every operation retains all component source revisions and before/after/rollback canonical mappings while Zotero records remain unchanged. Reviewed collection/tag changes produce a default-dry-run plan bound to exact server, library, item, rule, digest, and complete metadata preconditions; automatic-tag type is preserved and Zotero 9 execute mode is rejected. The injected execution core calls nothing in dry-run mode, preflights every item before a write, stops at the first failure, verifies post-write state, and emits reverse-ordered rollback operations using returned item revisions. Synthetic fixtures verify these contracts. Korean, Japanese, Chinese, Vietnamese, Spanish, German, and French ontology-alignment metadata now have explicit fail-closed abstention coverage alongside the existing English positive case; this is safety evidence, not translated classification support. No real precision/recall, duplicate merge, or write claim exists until a steward supplies reviewed local decisions and a production authorization adapter verifies them. AC6 still requires an authenticated Zotero 10+ HTTP transport plus approved live partial-failure and rollback evidence. Multilingual rule expansion remains a later evidence-driven change and must not reduce abstention safety. A dedicated utility repository remains unnecessary until an independently released cross-product contract exists. 1. **Concrete Source Observation adapter** — maintained Rust PostgreSQL driver behind `conceptweave-source-port`; adapter-local credential resolution; explicit read-only mode; statement timeout, cancellation, row/byte/concurrency budgets; complete immutable snapshot or fail closed; deterministic replay against a frozen anonymized GRC-shaped fixture. 2. **Ontology discovery** — deterministic term/concept/taxonomy/non-taxonomic-relation candidate generation with exact source receipts and abstention for unsupported semantics. From 81849c69b3c160c8bea10a7c5141a414480d5c0f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:21:01 +0900 Subject: [PATCH 4/6] test(zotero): require multilingual vocabulary abstention --- crates/conceptweave-zotero/tests/review_contract.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/conceptweave-zotero/tests/review_contract.rs b/crates/conceptweave-zotero/tests/review_contract.rs index 8215ed4c..48489289 100644 --- a/crates/conceptweave-zotero/tests/review_contract.rs +++ b/crates/conceptweave-zotero/tests/review_contract.rs @@ -45,13 +45,7 @@ fn steward_abstention_reason_is_explicit_and_deterministic() { ); assert!(report.classified_items[1..=7].iter().all(|item| { item.proposed_disposition == Disposition::NeedsStewardReview - && matches!( - item.abstention_reason, - Some( - AbstentionReason::UnsupportedRuleVocabulary - | AbstentionReason::NoDeterministicRuleMatch - ) - ) + && item.abstention_reason == Some(AbstentionReason::UnsupportedRuleVocabulary) })); assert_eq!( report.classified_items[8].abstention_reason, From 27f92340427bbb2c19667b720048d57f4fc200a0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:21:31 +0900 Subject: [PATCH 5/6] test(zotero): use explicit multilingual vocabulary fixtures --- crates/conceptweave-zotero/tests/review_contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/conceptweave-zotero/tests/review_contract.rs b/crates/conceptweave-zotero/tests/review_contract.rs index 48489289..0a7e80ea 100644 --- a/crates/conceptweave-zotero/tests/review_contract.rs +++ b/crates/conceptweave-zotero/tests/review_contract.rs @@ -25,8 +25,8 @@ fn steward_abstention_reason_is_explicit_and_deterministic() { ("D", "本体对齐"), ("E", "căn chỉnh bản thể"), ("F", "alineación de ontologías"), - ("G", "Ontologieabgleich"), - ("H", "alignement d’ontologies"), + ("G", "Ontologie-Ausrichtung für Wissensgraphen"), + ("H", "alignement d’ontologies sémantiques"), ] .map(|(key, title)| item(key, title, "")); let unmatched = item("I", "Other evidence", ""); From 84b27fb6b2563e0d4661905aa57702a0dde082ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 22:33:50 +0900 Subject: [PATCH 6/6] docs(research): record multilingual successor verification without capability inflation --- docs/product-technical-gap-baseline.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 01db27c8..a2274451 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -89,6 +89,26 @@ Remaining work: mandatory adoption by restoration, worksheet, duplicate and writ ## DDD fitness constraints +### PR #16 multilingual successor verification (2026-09-06) + +Baseline `044018cef4e5d3e919b278a1cfebe56857863601` passed 87 tests/19 suites. +Normal merge `4f3ac52a27ff1090b94c63ff807ddb5bd9ce872f` retains that entire delta +and parent `42ddd81adf8d994f67a30f0c6b8383d637073c72`. Production source is identical +to the repaired parent; `review_contract.rs` is identical to the prior PR #16. +An independent static review confirmed all seven non-English cases, English +match, blank metadata and unmatched metadata remain without reduced assertions. +This is abstention safety, not multilingual classification or completed research. + +Exact merged source passed 109 tests/19 result suites including three doctests, +strict all-target Clippy, warnings-denied rustdoc, format, CI-contract and diff +checks, plus the unchanged coverage gate: 185/185 functions, 1770/1770 normalized +regions and 320/320 normalized branches. Raw LLVM remains 1998/2050 lines, +2934/3014 regions and 280/320 branches, not 100%. Logs use the +`/tmp/conceptweave-pr16-scope-` prefix (`baseline`, `final`, `clippy`, `rustdoc`, +`coverage`, each with `.log`). No new production code, live write, paper decision, +approval, protected merge or release is claimed. Next owner is PR #17 authenticated +transport; it must preserve required bindings and indeterminate-request semantics. + ### PR #15 execution-scope and uncertainty repair (2026-09-06) Baseline `45e9c493` passed 87 tests/19 result suites; normal merge `2887f70`