From f7051ffbc167365b8e74870f32db42e0d70dc668 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:23:03 +0900 Subject: [PATCH 01/67] test(client): define semantic release admission contract --- Cargo.lock | 7 + Cargo.toml | 2 +- crates/conceptweave-client/Cargo.toml | 11 ++ crates/conceptweave-client/src/lib.rs | 3 + .../tests/release_validation.rs | 180 ++++++++++++++++++ 5 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 crates/conceptweave-client/Cargo.toml create mode 100644 crates/conceptweave-client/src/lib.rs create mode 100644 crates/conceptweave-client/tests/release_validation.rs diff --git a/Cargo.lock b/Cargo.lock index 451324f0..5755236a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,13 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "conceptweave-client" +version = "0.1.0" +dependencies = [ + "conceptweave-domain", +] + [[package]] name = "conceptweave-domain" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 0eec8e8c..afb4f9c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["crates/conceptweave-domain"] +members = ["crates/conceptweave-domain", "crates/conceptweave-client"] resolver = "2" [workspace.package] diff --git a/crates/conceptweave-client/Cargo.toml b/crates/conceptweave-client/Cargo.toml new file mode 100644 index 00000000..916fa583 --- /dev/null +++ b/crates/conceptweave-client/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "conceptweave-client" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true +description = "Offline semantic-release admission contracts for ConceptWeave consumers" + +[dependencies] +conceptweave-domain = { path = "../conceptweave-domain" } diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs new file mode 100644 index 00000000..2cf9a171 --- /dev/null +++ b/crates/conceptweave-client/src/lib.rs @@ -0,0 +1,3 @@ +#![forbid(unsafe_code)] +#![deny(missing_docs)] +//! Offline ConceptWeave semantic-release client contracts. diff --git a/crates/conceptweave-client/tests/release_validation.rs b/crates/conceptweave-client/tests/release_validation.rs new file mode 100644 index 00000000..6fd66c51 --- /dev/null +++ b/crates/conceptweave-client/tests/release_validation.rs @@ -0,0 +1,180 @@ +use conceptweave_client::{ + ReleaseContractError, ReleaseDigest, SemanticRelease, SemanticReleaseClient, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_evidence.control_identifier", + ) + .unwrap() +} + +fn digest() -> ReleaseDigest { + ReleaseDigest::new("sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") + .unwrap() +} + +fn release( + contract_version: &str, + truth_status: TruthStatus, + publication_state: PublicationState, +) -> SemanticRelease { + SemanticRelease::new( + "semantic-release-grc-2026-09-01", + contract_version, + "grc-ontology-2026-09", + truth_status, + publication_state, + digest(), + vec![evidence()], + vec!["control.evidence".to_string(), "control.owner".to_string()], + ) + .unwrap() +} + +#[test] +fn authoritative_published_release_is_admitted_offline() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release( + "1.0.0", + TruthStatus::Authoritative, + PublicationState::Published, + ); + + assert_eq!(client.validate_for_authoritative_use(&release), Ok(())); +} + +#[test] +fn client_fails_closed_on_unpublished_or_non_authoritative_release() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + + let reviewed = release( + "1.0.0", + TruthStatus::Inferred, + PublicationState::Reviewed, + ); + assert_eq!( + client.validate_for_authoritative_use(&reviewed), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }) + ); + + let wrong_truth = release( + "1.0.0", + TruthStatus::Proposed, + PublicationState::Published, + ); + assert_eq!( + client.validate_for_authoritative_use(&wrong_truth), + Err(ReleaseContractError::ReleaseNotAuthoritative { + actual: TruthStatus::Proposed, + }) + ); +} + +#[test] +fn client_rejects_unsupported_contract_version_before_use() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release( + "2.0.0", + TruthStatus::Authoritative, + PublicationState::Published, + ); + + assert_eq!( + client.validate_for_authoritative_use(&release), + Err(ReleaseContractError::UnsupportedContractVersion { + expected: "1.0.0".to_string(), + actual: "2.0.0".to_string(), + }) + ); +} + +#[test] +fn release_requires_identity_provenance_and_unique_non_blank_concepts() { + assert_eq!( + SemanticRelease::new( + " ", + "1.0.0", + "ontology-1", + TruthStatus::Authoritative, + PublicationState::Published, + digest(), + vec![evidence()], + vec!["concept.one".to_string()], + ), + Err(ReleaseContractError::EmptyField("release_id")) + ); + + assert_eq!( + SemanticRelease::new( + "release-1", + "1.0.0", + "ontology-1", + TruthStatus::Authoritative, + PublicationState::Published, + digest(), + vec![], + vec!["concept.one".to_string()], + ), + Err(ReleaseContractError::MissingProvenance) + ); + + assert_eq!( + SemanticRelease::new( + "release-1", + "1.0.0", + "ontology-1", + TruthStatus::Authoritative, + PublicationState::Published, + digest(), + vec![evidence()], + vec![" ".to_string()], + ), + Err(ReleaseContractError::EmptyField("concept_id")) + ); + + assert_eq!( + SemanticRelease::new( + "release-1", + "1.0.0", + "ontology-1", + TruthStatus::Authoritative, + PublicationState::Published, + digest(), + vec![evidence()], + vec!["concept.one".to_string(), "concept.one".to_string()], + ), + Err(ReleaseContractError::DuplicateConceptId( + "concept.one".to_string() + )) + ); +} + +#[test] +fn digest_contract_rejects_non_sha256_and_malformed_hex() { + assert_eq!( + ReleaseDigest::new("md5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + Err(ReleaseContractError::InvalidDigest) + ); + assert_eq!( + ReleaseDigest::new("sha256:abc"), + Err(ReleaseContractError::InvalidDigest) + ); + assert_eq!( + ReleaseDigest::new("sha256:gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"), + Err(ReleaseContractError::InvalidDigest) + ); +} + +#[test] +fn client_requires_non_blank_supported_contract_version() { + assert_eq!( + SemanticReleaseClient::new(" "), + Err(ReleaseContractError::EmptyField("supported_contract_version")) + ); +} From a402c700ffa8270235571297304469a10e96d3b2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:24:14 +0900 Subject: [PATCH 02/67] test(client): cover release metadata invariants --- .../tests/release_validation.rs | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/crates/conceptweave-client/tests/release_validation.rs b/crates/conceptweave-client/tests/release_validation.rs index 6fd66c51..2345b0e6 100644 --- a/crates/conceptweave-client/tests/release_validation.rs +++ b/crates/conceptweave-client/tests/release_validation.rs @@ -44,6 +44,18 @@ fn authoritative_published_release_is_admitted_offline() { PublicationState::Published, ); + assert_eq!(client.supported_contract_version(), "1.0.0"); + assert_eq!(release.release_id(), "semantic-release-grc-2026-09-01"); + assert_eq!(release.contract_version(), "1.0.0"); + assert_eq!(release.ontology_version(), "grc-ontology-2026-09"); + assert_eq!(release.truth_status(), TruthStatus::Authoritative); + assert_eq!(release.publication_state(), PublicationState::Published); + assert_eq!( + release.artifact_digest().as_str(), + "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + ); + assert_eq!(release.provenance().len(), 1); + assert_eq!(release.concept_ids(), ["control.evidence", "control.owner"]); assert_eq!(client.validate_for_authoritative_use(&release), Ok(())); } @@ -95,20 +107,26 @@ fn client_rejects_unsupported_contract_version_before_use() { } #[test] -fn release_requires_identity_provenance_and_unique_non_blank_concepts() { - assert_eq!( - SemanticRelease::new( - " ", - "1.0.0", - "ontology-1", - TruthStatus::Authoritative, - PublicationState::Published, - digest(), - vec![evidence()], - vec!["concept.one".to_string()], - ), - Err(ReleaseContractError::EmptyField("release_id")) - ); +fn release_requires_identity_versions_provenance_and_unique_non_blank_concepts() { + for (release_id, contract_version, ontology_version, expected_field) in [ + (" ", "1.0.0", "ontology-1", "release_id"), + ("release-1", " ", "ontology-1", "contract_version"), + ("release-1", "1.0.0", " ", "ontology_version"), + ] { + assert_eq!( + SemanticRelease::new( + release_id, + contract_version, + ontology_version, + TruthStatus::Authoritative, + PublicationState::Published, + digest(), + vec![evidence()], + vec!["concept.one".to_string()], + ), + Err(ReleaseContractError::EmptyField(expected_field)) + ); + } assert_eq!( SemanticRelease::new( From c65474e3c9f8ed5dd47dd04c633929f627160d69 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:24:44 +0900 Subject: [PATCH 03/67] test(client): specify actionable admission errors --- .../tests/error_messages.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 crates/conceptweave-client/tests/error_messages.rs diff --git a/crates/conceptweave-client/tests/error_messages.rs b/crates/conceptweave-client/tests/error_messages.rs new file mode 100644 index 00000000..c5ce1e5c --- /dev/null +++ b/crates/conceptweave-client/tests/error_messages.rs @@ -0,0 +1,48 @@ +use conceptweave_client::ReleaseContractError; +use conceptweave_domain::{PublicationState, TruthStatus}; + +#[test] +fn contract_errors_explain_the_failed_admission_invariant() { + let cases = [ + ( + ReleaseContractError::EmptyField("release_id"), + "required field `release_id` is blank".to_string(), + ), + ( + ReleaseContractError::InvalidDigest, + "release digest must use sha256:<64 hex>".to_string(), + ), + ( + ReleaseContractError::MissingProvenance, + "semantic releases require provenance evidence".to_string(), + ), + ( + ReleaseContractError::DuplicateConceptId("concept.one".to_string()), + "semantic release contains duplicate concept id `concept.one`".to_string(), + ), + ( + ReleaseContractError::UnsupportedContractVersion { + expected: "1.0.0".to_string(), + actual: "2.0.0".to_string(), + }, + "semantic release contract version `2.0.0` is unsupported; expected `1.0.0`" + .to_string(), + ), + ( + ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }, + "semantic release is Reviewed, not Published".to_string(), + ), + ( + ReleaseContractError::ReleaseNotAuthoritative { + actual: TruthStatus::Proposed, + }, + "semantic release truth status is Proposed, not Authoritative".to_string(), + ), + ]; + + for (error, expected) in cases { + assert_eq!(error.to_string(), expected); + } +} From 8149f0d15a9f679edb5b2d54b552dc67e8639215 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:25:29 +0900 Subject: [PATCH 04/67] feat(client): implement offline semantic release admission --- crates/conceptweave-client/src/lib.rs | 265 ++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 2cf9a171..03f1e201 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -1,3 +1,268 @@ #![forbid(unsafe_code)] #![deny(missing_docs)] //! Offline ConceptWeave semantic-release client contracts. +//! +//! This crate is intentionally provider- and transport-independent. A consumer +//! can inspect release identity, provenance and governance state before making +//! authoritative use of a semantic release. Generator-private classes, source +//! database access and LLM orchestration stay outside this boundary. + +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; +use core::fmt; +use std::collections::BTreeSet; + +/// A validated content-digest identity carried by a semantic release. +/// +/// The current contract accepts only the explicit `sha256:<64 hex>` shape. This +/// value object validates digest identity syntax; byte-for-byte cryptographic +/// re-hashing belongs to the serialized-artifact verification adapter. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ReleaseDigest(String); + +impl ReleaseDigest { + /// Parses a release digest and rejects unsupported algorithms or malformed hex. + pub fn new(value: impl Into) -> Result { + let value = value.into(); + let Some(hex) = value.strip_prefix("sha256:") else { + return Err(ReleaseContractError::InvalidDigest); + }; + if hex.len() != 64 { + return Err(ReleaseContractError::InvalidDigest); + } + if !hex.bytes().all(|byte| byte.is_ascii_hexdigit()) { + return Err(ReleaseContractError::InvalidDigest); + } + Ok(Self(value)) + } + + /// Returns the canonical digest identity string. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +/// Immutable client-visible metadata required to admit a semantic release. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SemanticRelease { + release_id: String, + contract_version: String, + ontology_version: String, + truth_status: TruthStatus, + publication_state: PublicationState, + artifact_digest: ReleaseDigest, + provenance: Vec, + concept_ids: Vec, +} + +impl SemanticRelease { + /// Constructs a structurally valid semantic release contract. + /// + /// Construction validates stable identity, version metadata, provenance and + /// concept identity uniqueness. Whether the release is safe for authoritative + /// use is a separate client-policy decision performed by + /// [`SemanticReleaseClient::validate_for_authoritative_use`]. + #[allow(clippy::too_many_arguments)] + pub fn new( + release_id: impl Into, + contract_version: impl Into, + ontology_version: impl Into, + truth_status: TruthStatus, + publication_state: PublicationState, + artifact_digest: ReleaseDigest, + provenance: Vec, + concept_ids: Vec, + ) -> Result { + let release_id = release_id.into(); + let contract_version = contract_version.into(); + let ontology_version = ontology_version.into(); + + require_non_blank(&release_id, "release_id")?; + require_non_blank(&contract_version, "contract_version")?; + require_non_blank(&ontology_version, "ontology_version")?; + if provenance.is_empty() { + return Err(ReleaseContractError::MissingProvenance); + } + + let mut unique_concepts = BTreeSet::new(); + for concept_id in &concept_ids { + require_non_blank(concept_id, "concept_id")?; + if !unique_concepts.insert(concept_id.as_str()) { + return Err(ReleaseContractError::DuplicateConceptId( + concept_id.clone(), + )); + } + } + + Ok(Self { + release_id, + contract_version, + ontology_version, + truth_status, + publication_state, + artifact_digest, + provenance, + concept_ids, + }) + } + + /// Returns the stable semantic-release identity. + pub fn release_id(&self) -> &str { + &self.release_id + } + + /// Returns the client contract version encoded by this release. + pub fn contract_version(&self) -> &str { + &self.contract_version + } + + /// Returns the ontology/model version carried by this release. + pub fn ontology_version(&self) -> &str { + &self.ontology_version + } + + /// Returns the release truth status. + pub fn truth_status(&self) -> TruthStatus { + self.truth_status + } + + /// Returns the governance/publication state of this release. + pub fn publication_state(&self) -> PublicationState { + self.publication_state + } + + /// Returns the declared immutable artifact digest identity. + pub fn artifact_digest(&self) -> &ReleaseDigest { + &self.artifact_digest + } + + /// Returns immutable evidence/provenance references for this release. + pub fn provenance(&self) -> &[EvidenceReference] { + &self.provenance + } + + /// Returns stable concept identifiers carried by this release. + pub fn concept_ids(&self) -> &[String] { + &self.concept_ids + } +} + +/// Offline admission policy for one supported semantic-release contract version. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SemanticReleaseClient { + supported_contract_version: String, +} + +impl SemanticReleaseClient { + /// Creates a client pinned to one explicit semantic-release contract version. + pub fn new( + supported_contract_version: impl Into, + ) -> Result { + let supported_contract_version = supported_contract_version.into(); + require_non_blank( + &supported_contract_version, + "supported_contract_version", + )?; + Ok(Self { + supported_contract_version, + }) + } + + /// Returns the exact semantic-release contract version this client accepts. + pub fn supported_contract_version(&self) -> &str { + &self.supported_contract_version + } + + /// Fails closed unless a release is compatible, Published and Authoritative. + /// + /// This check is deterministic and performs no network or model calls. It is + /// suitable as an admission gate before a consuming product performs its own + /// tenant/purpose authorization and physical query planning. + pub fn validate_for_authoritative_use( + &self, + release: &SemanticRelease, + ) -> Result<(), ReleaseContractError> { + if release.contract_version != self.supported_contract_version { + return Err(ReleaseContractError::UnsupportedContractVersion { + expected: self.supported_contract_version.clone(), + actual: release.contract_version.clone(), + }); + } + if release.publication_state != PublicationState::Published { + return Err(ReleaseContractError::ReleaseNotPublished { + actual: release.publication_state, + }); + } + if release.truth_status != TruthStatus::Authoritative { + return Err(ReleaseContractError::ReleaseNotAuthoritative { + actual: release.truth_status, + }); + } + Ok(()) + } +} + +fn require_non_blank(value: &str, field: &'static str) -> Result<(), ReleaseContractError> { + if value.trim().is_empty() { + return Err(ReleaseContractError::EmptyField(field)); + } + Ok(()) +} + +/// A deterministic semantic-release contract or admission failure. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ReleaseContractError { + /// A required stable identity or version field was blank. + EmptyField(&'static str), + /// The declared release digest is not `sha256:<64 hex>`. + InvalidDigest, + /// The release carries no provenance evidence. + MissingProvenance, + /// The release repeats one semantic concept identity. + DuplicateConceptId(String), + /// The release uses a contract version this client does not support. + UnsupportedContractVersion { + /// Contract version required by the client. + expected: String, + /// Contract version supplied by the release. + actual: String, + }, + /// The release has not crossed the governed Published boundary. + ReleaseNotPublished { + /// Actual release publication state. + actual: PublicationState, + }, + /// The release is Published but its truth status is not Authoritative. + ReleaseNotAuthoritative { + /// Actual release truth status. + actual: TruthStatus, + }, +} + +impl fmt::Display for ReleaseContractError { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::EmptyField(field) => write!(formatter, "required field `{field}` is blank"), + Self::InvalidDigest => write!(formatter, "release digest must use sha256:<64 hex>"), + Self::MissingProvenance => { + write!(formatter, "semantic releases require provenance evidence") + } + Self::DuplicateConceptId(concept_id) => write!( + formatter, + "semantic release contains duplicate concept id `{concept_id}`" + ), + Self::UnsupportedContractVersion { expected, actual } => write!( + formatter, + "semantic release contract version `{actual}` is unsupported; expected `{expected}`" + ), + Self::ReleaseNotPublished { actual } => { + write!(formatter, "semantic release is {actual:?}, not Published") + } + Self::ReleaseNotAuthoritative { actual } => write!( + formatter, + "semantic release truth status is {actual:?}, not Authoritative" + ), + } + } +} + +impl std::error::Error for ReleaseContractError {} From 7aec6547e56cbe8f4fc76229d69d8b1b738e9b11 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:27:37 +0900 Subject: [PATCH 05/67] test(contract): require semantic release JSON validation --- .github/workflows/product.yml | 25 ++++++++++++++++++- .../semantic-release.invalid-digest.json | 16 ++++++++++++ ...tic-release.invalid-duplicate-concept.json | 16 ++++++++++++ ...antic-release.invalid-published-truth.json | 16 ++++++++++++ .../fixtures/semantic-release.valid.json | 16 ++++++++++++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 contracts/fixtures/semantic-release.invalid-digest.json create mode 100644 contracts/fixtures/semantic-release.invalid-duplicate-concept.json create mode 100644 contracts/fixtures/semantic-release.invalid-published-truth.json create mode 100644 contracts/fixtures/semantic-release.valid.json diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index d49caaf1..47d28405 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -61,7 +61,7 @@ jobs: - name: Exact owned coverage run: ./scripts/check_coverage.sh - - name: Validate public JSON contract + - name: Validate public JSON contracts run: | npx --yes ajv-cli@5.0.0 compile \ --spec=draft2020 \ @@ -81,6 +81,29 @@ jobs: -s contracts/semantic-candidate.schema.json \ -d contracts/fixtures/semantic-candidate.invalid-published-truth.json \ --invalid + npx --yes ajv-cli@5.0.0 compile \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.valid.json \ + --valid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-published-truth.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-duplicate-concept.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-digest.json \ + --invalid - name: Lockfile freshness run: | diff --git a/contracts/fixtures/semantic-release.invalid-digest.json b/contracts/fixtures/semantic-release.invalid-digest.json new file mode 100644 index 00000000..2e56c579 --- /dev/null +++ b/contracts/fixtures/semantic-release.invalid-digest.json @@ -0,0 +1,16 @@ +{ + "release_id": "semantic-release-grc-2026-09-01", + "contract_version": "1.0.0", + "ontology_version": "grc-ontology-2026-09", + "truth_status": "authoritative", + "publication_state": "published", + "artifact_digest": "sha256:not-a-digest", + "provenance": [ + { + "source_id": "snapshot:grc-schema-2026-09-01", + "source_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "location": "public.control_evidence.control_identifier" + } + ], + "concept_ids": ["control.evidence"] +} diff --git a/contracts/fixtures/semantic-release.invalid-duplicate-concept.json b/contracts/fixtures/semantic-release.invalid-duplicate-concept.json new file mode 100644 index 00000000..2d9945cc --- /dev/null +++ b/contracts/fixtures/semantic-release.invalid-duplicate-concept.json @@ -0,0 +1,16 @@ +{ + "release_id": "semantic-release-grc-2026-09-01", + "contract_version": "1.0.0", + "ontology_version": "grc-ontology-2026-09", + "truth_status": "authoritative", + "publication_state": "published", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "provenance": [ + { + "source_id": "snapshot:grc-schema-2026-09-01", + "source_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "location": "public.control_evidence.control_identifier" + } + ], + "concept_ids": ["control.evidence", "control.evidence"] +} diff --git a/contracts/fixtures/semantic-release.invalid-published-truth.json b/contracts/fixtures/semantic-release.invalid-published-truth.json new file mode 100644 index 00000000..828b9a6a --- /dev/null +++ b/contracts/fixtures/semantic-release.invalid-published-truth.json @@ -0,0 +1,16 @@ +{ + "release_id": "semantic-release-grc-2026-09-01", + "contract_version": "1.0.0", + "ontology_version": "grc-ontology-2026-09", + "truth_status": "proposed", + "publication_state": "published", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "provenance": [ + { + "source_id": "snapshot:grc-schema-2026-09-01", + "source_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "location": "public.control_evidence.control_identifier" + } + ], + "concept_ids": ["control.evidence"] +} diff --git a/contracts/fixtures/semantic-release.valid.json b/contracts/fixtures/semantic-release.valid.json new file mode 100644 index 00000000..59fc33df --- /dev/null +++ b/contracts/fixtures/semantic-release.valid.json @@ -0,0 +1,16 @@ +{ + "release_id": "semantic-release-grc-2026-09-01", + "contract_version": "1.0.0", + "ontology_version": "grc-ontology-2026-09", + "truth_status": "authoritative", + "publication_state": "published", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "provenance": [ + { + "source_id": "snapshot:grc-schema-2026-09-01", + "source_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "location": "public.control_evidence.control_identifier" + } + ], + "concept_ids": ["control.evidence", "control.owner"] +} From 37300c4ec4e29394e6745309b96d112fb4cc6ee8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:28:16 +0900 Subject: [PATCH 06/67] feat(contract): add semantic release JSON schema --- contracts/semantic-release.schema.json | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 contracts/semantic-release.schema.json diff --git a/contracts/semantic-release.schema.json b/contracts/semantic-release.schema.json new file mode 100644 index 00000000..52c2d41d --- /dev/null +++ b/contracts/semantic-release.schema.json @@ -0,0 +1,109 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.contextualwisdomlab.org/conceptweave/semantic-release/1.0.0", + "title": "ConceptWeave Semantic Release", + "type": "object", + "additionalProperties": false, + "required": [ + "release_id", + "contract_version", + "ontology_version", + "truth_status", + "publication_state", + "artifact_digest", + "provenance", + "concept_ids" + ], + "properties": { + "release_id": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "contract_version": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "ontology_version": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "truth_status": { + "enum": [ + "observed", + "inferred", + "proposed", + "authoritative", + "superseded", + "rejected" + ] + }, + "publication_state": { + "enum": [ + "draft", + "proposed", + "validated", + "reviewed", + "published", + "superseded", + "rejected" + ] + }, + "artifact_digest": { + "type": "string", + "pattern": "^sha256:[0-9A-Fa-f]{64}$" + }, + "provenance": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["source_id", "source_digest", "location"], + "properties": { + "source_id": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "source_digest": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "location": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + } + } + } + }, + "concept_ids": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + } + } + }, + "allOf": [ + { + "if": { + "properties": { + "publication_state": {"const": "published"} + }, + "required": ["publication_state"] + }, + "then": { + "properties": { + "truth_status": {"const": "authoritative"} + } + } + } + ] +} From 49367f647770acb281b156486c8ca34cc21693b6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:34:42 +0900 Subject: [PATCH 07/67] docs(client): define release consumption boundary --- ARCHITECTURE.md | 41 ++++++++---- CHANGELOG.md | 8 ++- SECURITY.md | 13 ++-- TEST_STRATEGY.md | 33 ++++++++-- docs/CONTEXT_MAP.md | 11 +++- docs/PRD.md | 24 +++++-- docs/TRD.md | 43 ++++++++---- docs/UBIQUITOUS_LANGUAGE.md | 9 ++- docs/UML.md | 25 ++++++- .../0004-semantic-release-client-boundary.md | 65 +++++++++++++++++++ docs/adr/README.md | 1 + docs/product-technical-gap-baseline.md | 59 ++++++++++++----- 12 files changed, 265 insertions(+), 67 deletions(-) create mode 100644 docs/adr/0004-semantic-release-client-boundary.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index c5dd4993..4ac642a5 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -2,7 +2,7 @@ ## Product responsibility -ConceptWeave owns the process that turns observed enterprise evidence into governed semantic-model releases. It does not own source-system truth or downstream catalog/query experiences. +ConceptWeave owns the process that turns observed enterprise evidence into governed semantic-model releases and the stable client contract used to inspect those releases. It does not own source-system truth, consuming-product authorization, physical query execution, or downstream catalog/search experiences. ```mermaid flowchart LR @@ -11,13 +11,15 @@ flowchart LR D --> V[Model Validation] V --> G[Governance & Publication] G --> P[Versioned semantic release] + P --> C[Client Consumption] - CO[contextual-orchestrator] -. proposal assistance .-> D + CO[contextual-orchestrator] -. proposal or optional alignment assistance .-> D + CO -. optional bounded matching assistance .-> C LW[LineageWeave] -. inferred/proposed lineage .-> O CG[context-graph-contracts] -. shared graph/provenance contracts .-> P - P --> SDP[semantic-data-portal] - P --> GRC[governance-risk-compliance] - P --> EA[enterprise-architecture-core] + C --> SDP[semantic-data-portal] + C --> GRC[governance-risk-compliance] + C --> EA[enterprise-architecture-core] ``` ## DDD context map @@ -28,17 +30,28 @@ flowchart LR | Semantic Discovery | Core | candidate generation and evidence binding | publication authority | | Model Validation | Supporting | deterministic validation reports | human review decisions | | Governance & Publication | Core | proposal lifecycle, review receipts, releases, supersession | catalog/search runtime | +| Client Consumption | Supporting | release admission, compatibility, future diff/match/resolve/query-plan contracts | generator internals, consumer authorization, physical query execution | | Interoperability | Supporting | versioned import/export and ACL adapters | foreign product internals | -## Aggregate boundaries +The generation-to-client dependency crosses only versioned public release contracts. Client code may reuse public domain value types, but it must not import generator-private adapters, prompts, persistence tables, or orchestration state. + +## Aggregate and value-object boundaries ### SemanticCandidate Smallest consistency boundary for a single proposed semantic artifact and its evidence-bound publication state. It cannot jump directly from Draft to Published. -### SemanticModelRelease (planned) +### SemanticModelRelease + +Planned Governance & Publication aggregate for immutable publication. The current Client slice defines only the consumer-visible release contract: stable release identity, contract and ontology versions, truth/publication state, declared artifact digest identity, provenance references, and stable concept identifiers. Release construction is not publication authority. + +### ReleaseDigest + +Client value object for a declared `sha256:<64 hex>` digest identity. It validates digest syntax only. A later serialized-artifact verifier must hash the exact bytes and compare the result before integrity is claimed. + +### SemanticReleaseClient -Immutable publication aggregate containing approved candidate identities, release version, artifact digests, validation receipts, reviewer receipts, and supersession metadata. It will reference candidates rather than copy foreign source records. +A stateless domain service in Client Consumption that admits a release for authoritative use only when the contract version is supported and the release is both `Published` and `Authoritative`. It performs no network, LLM, database, tenant-authorization, or physical-query work. ## Truth model @@ -49,24 +62,26 @@ Immutable publication aggregate containing approved candidate identities, releas - `superseded`: formerly authoritative and replaced; - `rejected`: explicitly rejected. -Truth status and publication workflow are distinct. A source observation can be authoritative in its source domain without making an inferred semantic interpretation authoritative. +Truth status and publication workflow are distinct. A source observation can be authoritative in its source domain without making an inferred semantic interpretation authoritative. Client admission fails closed rather than coercing these states. ## Integration boundaries -- `contextual-orchestrator`: LLM/model routing only. +- `contextual-orchestrator`: all production LLM/model routing; optional future matching/explanation is still proposal evidence. - `LineageWeave`: inferred/proposed lineage evidence only. - `semantic-data-portal`: published semantic artifact consumer/governance/catalog plane; it is not ConceptWeave's internal database. - `context-graph-contracts`: shared cross-product identifiers, truth/provenance/event contracts where adopted. - Keyverse: future identity/tenant authentication boundary. +- Consuming products: retain tenant/purpose authorization, business-domain truth, and physical data/query execution behind their own ACLs. No direct cross-service application-table SQL is permitted. -## Foundation directory structure +## Current directory structure ```text crates/ - conceptweave-domain/ # Core domain contract only -contracts/ # Versioned public schemas + conceptweave-domain/ # Core candidate/evidence lifecycle contracts + conceptweave-client/ # Offline release admission and compatibility boundary +contracts/ # Versioned public JSON Schemas and fixtures docs/ adr/ # Binding architecture decisions doctoring/ # Standards/research evidence diff --git a/CHANGELOG.md b/CHANGELOG.md index 8910d6fa..7705b75e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,13 @@ All notable changes to ConceptWeave are documented here. - Rust 1.98.0 `conceptweave-domain` foundation with evidence-bound semantic candidate contracts. - Fail-closed Draft -> Proposed -> Validated -> Reviewed -> Published lifecycle with explicit rejection and supersession. - Draft 2020-12 JSON Schema for the semantic-candidate public contract. -- Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering research. +- Rust-first `conceptweave-client` supporting subdomain with deterministic offline semantic-release admission by contract version, publication state, truth status, provenance, stable concept identity, and declared SHA-256 digest identity. +- Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. +- Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. ### Security - Model-generated semantics remain non-authoritative until deterministic validation and authorized review. -- Unsafe Rust is forbidden in the core domain crate. +- Client authoritative-use admission rejects incompatible, unpublished, or non-authoritative releases without requiring a network/model call. +- Declared digest syntax validation is explicitly separated from future cryptographic byte verification to prevent false integrity claims. +- Unsafe Rust is forbidden in the core domain and client crates. diff --git a/SECURITY.md b/SECURITY.md index 5d930ad0..f1a5ff7b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ ## Trust boundaries -All source artifacts, generated candidate payloads, external ontology files, model outputs, and future web-retrieved content are untrusted input. +All source artifacts, generated candidate payloads, external ontology files, model outputs, future web-retrieved content, and semantic-release payloads received by a client are untrusted input. ## Required controls @@ -14,6 +14,9 @@ All source artifacts, generated candidate payloads, external ontology files, mod - outbound retrieval, when introduced, uses a reviewed SSRF/DNS-rebinding-safe CWL egress boundary; - no source-system writes from discovery or validation; - reviewed authorization required before publication; +- client authoritative-use admission must fail closed on unsupported contract versions, non-Published state, or non-Authoritative truth status; +- client admission does not substitute for consuming-product tenant/purpose authorization; +- declared release digest syntax is not an integrity claim: exact serialized bytes must be hashed and compared before cryptographic integrity is asserted; - future tenant isolation applies to source snapshots, candidates, review receipts, releases, exports, and object storage; - published semantic truth is immutable: a published artifact must never be overwritten in place, including when an audit trail exists; corrections are issued as a new release that explicitly supersedes the prior release while retaining both releases and their provenance. @@ -24,11 +27,13 @@ All source artifacts, generated candidate payloads, external ontology files, mod 3. ontology import cycles or reasoning/resource exhaustion; 4. unsafe generated query/expression execution; 5. cross-tenant evidence exposure; -6. provenance stripping during export; -7. malicious or oversized schema/API artifacts; +6. provenance stripping during export or consumption; +7. malicious or oversized schema/API/release artifacts; 8. external-source SSRF or credential leakage; 9. model/provider compromise or unexpected retention; 10. governance bypass from Proposed/Validated directly to Published; -11. in-place mutation or overwrite of previously published semantic truth. +11. in-place mutation or overwrite of previously published semantic truth; +12. consumer use of an incompatible, unpublished, non-authoritative, stale, or superseded release; +13. false integrity claims caused by checking digest syntax without hashing the exact artifact bytes. Security findings become tests before the related runtime capability can be marked release-ready. diff --git a/TEST_STRATEGY.md b/TEST_STRATEGY.md index 6d137795..ccbb8d43 100644 --- a/TEST_STRATEGY.md +++ b/TEST_STRATEGY.md @@ -3,11 +3,26 @@ ## Foundation gates - Rust formatting and Clippy with warnings denied; -- unit tests for every domain lifecycle branch; +- unit/integration tests for every owned domain/client behavior branch; - owned production line/function/region and LLVM branch coverage target of 100%; -- JSON Schema syntax validation; +- Draft 2020-12 JSON Schema syntax and positive/negative fixture validation for public contracts; - lockfile freshness and clean-tree verification; -- public Rust documentation with `missing_docs` denied. +- public Rust documentation with `missing_docs` denied; +- every CI result is valid only for the unchanged exact PR head. + +## Current Client Consumption tests + +- authoritative + Published release admits offline for the exact supported contract version; +- Reviewed/unpublished and Published/non-Authoritative releases fail closed; +- unsupported contract versions fail closed; +- release/contract/ontology identifiers reject blank values; +- provenance is required; +- concept identifiers reject blanks and duplicates; +- declared digest identity rejects unsupported algorithm, wrong length, and non-hex payloads; +- public error messages identify the rejected admission invariant; +- JSON Schema fixtures mirror Published -> Authoritative, unique concepts, provenance and digest-shape constraints. + +Digest identity tests do not claim byte integrity. A future verifier must add golden exact-byte hashing plus one-byte mutation, truncation, serialization/canonicalization, wrong-digest and signature/provenance cases before integrity is release-ready. ## Future product test families @@ -19,6 +34,14 @@ Realistic PostgreSQL schema snapshots, OpenAPI/AsyncAPI fixtures, malformed cont Golden concept/type/taxonomy/relation sets; mapping precision/recall; multilingual labels; synonyms/homonyms; false friends; unrelated sources; cross-domain collisions; explicit no-answer cases. +### Client compatibility and alignment + +Current, older-supported, unsupported, malformed, partial, conflicting, stale and superseded releases; exact release diff; candidate-retrieval recall; OAEI-style matching precision/recall/F1; deterministic preprocessing ablations; abstention/ambiguity handling; LLM-call reduction against naive full-prompt baselines. Optional model calls use `contextual-orchestrator`; no model judge is sole truth. + +### Query-plan seam + +Golden semantic query plans preserve governed dimensions/measures/relations while physical execution and tenant/purpose authorization remain in the consuming product. Tests must prove no direct foreign application-table SQL or cross-tenant authorization bypass. + ### Semantic measures Exact deterministic calculations, grain correctness, join/cardinality safety, units, null semantics, time windows, currency/unit conversions through approved deterministic layers, and no LLM arithmetic authority. @@ -33,8 +56,8 @@ No bypass of Reviewed before Published, immutable published releases, rejection, ### Security -Prompt injection, malicious ontology/source content, SSRF, cross-tenant leakage, secret leakage, expression injection, resource exhaustion, replay, malformed source provenance, and hostile export values. +Prompt injection, malicious ontology/source/release content, SSRF, cross-tenant leakage, secret leakage, expression injection, resource exhaustion, replay, malformed source provenance, hostile export values, compatibility downgrade, stale/superseded use, and artifact tampering. ### Evaluation -Model-backed evaluation must include deterministic fixtures and human-reviewed expert cases. Report extraction recall, semantic precision, structural validity, mapping accuracy, citation/provenance completeness, and abstention quality separately rather than collapsing them into one opaque score. +Model-backed evaluation must include deterministic fixtures and human-reviewed expert cases. Report extraction recall, semantic precision, structural validity, mapping accuracy, citation/provenance completeness, compatibility correctness, and abstention quality separately rather than collapsing them into one opaque score. diff --git a/docs/CONTEXT_MAP.md b/docs/CONTEXT_MAP.md index 5ea47792..531338d6 100644 --- a/docs/CONTEXT_MAP.md +++ b/docs/CONTEXT_MAP.md @@ -5,12 +5,17 @@ - Source Observation -> Semantic Discovery: **Customer/Supplier**; Discovery consumes immutable observation contracts. - Semantic Discovery -> Model Validation: **Conformist to published candidate contract**; validation must not rewrite discovery evidence. - Model Validation -> Governance & Publication: **Customer/Supplier**; governance consumes deterministic validation receipts. -- Governance & Publication -> Interoperability: **Published Language**; adapters consume immutable release contracts. +- Governance & Publication -> Client Consumption: **Published Language**; clients consume immutable, versioned semantic-release contracts and never generator-private implementation. +- Governance & Publication -> Interoperability: **Published Language**; export adapters consume immutable release contracts. +- Client Consumption -> Interoperability: **Customer/Supplier** for versioned consumer bindings/adapters only; deterministic admission remains usable without an adapter or LLM. ## External relationships - contextual-orchestrator -> Semantic Discovery: **Anti-Corruption Layer**. Model/provider envelopes never enter the domain model directly. +- contextual-orchestrator -> future Model Alignment/Client Consumption assistance: **Anti-Corruption Layer**. Matching/explanation outputs remain candidate evidence and never grant authority. - LineageWeave -> Source Observation: **Anti-Corruption Layer**. Inferred/proposed lineage remains explicitly non-authoritative until ConceptWeave governance evaluates it. - context-graph-contracts <-> Interoperability: **Shared Kernel only for versioned public contracts**, kept minimal. -- semantic-data-portal <- Interoperability: **Published Language**. SDP consumes releases; ConceptWeave does not read SDP application tables. -- Keyverse -> future delivery layer: **Anti-Corruption Layer** for verified identity/tenant context. +- semantic-data-portal <- Client Consumption/Interoperability: **Published Language**. SDP consumes releases; ConceptWeave does not read SDP application tables. +- governance-risk-compliance <- Client Consumption: **Published Language + downstream ACL**. GRC validates/uses releases while retaining business truth, tenant/purpose authorization, and physical execution. +- enterprise-architecture-core <- Client Consumption: **Published Language + downstream ACL** under the same boundary. +- Keyverse -> future delivery/consumer authorization seams: **Anti-Corruption Layer** for verified identity/tenant context; ConceptWeave does not take ownership of downstream authorization policy. diff --git a/docs/PRD.md b/docs/PRD.md index 0e68c400..5e17389d 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -2,11 +2,11 @@ ## 1. Product statement -ConceptWeave converts heterogeneous enterprise evidence into a governed ontology and semantic layer without collapsing observed facts, model inference, and human-approved meaning into the same truth state. +ConceptWeave converts heterogeneous enterprise evidence into a governed ontology and semantic layer without collapsing observed facts, model inference, and human-approved meaning into the same truth state. It also exposes a stable consumer contract so downstream products can reject incompatible or non-authoritative releases without understanding generation internals. ## 2. Buyer problem -Enterprise teams repeatedly hand-build business glossaries, ontologies, metric definitions, semantic mappings, and data relationships from database schemas, API contracts, documents, and tribal knowledge. The work is slow, inconsistent across tools, difficult to audit, and unsafe to delegate entirely to an LLM because inferred semantics can be plausible but wrong. +Enterprise teams repeatedly hand-build business glossaries, ontologies, metric definitions, semantic mappings, and data relationships from database schemas, API contracts, documents, and tribal knowledge. The work is slow, inconsistent across tools, difficult to audit, and unsafe to delegate entirely to an LLM because inferred semantics can be plausible but wrong. Even after a model is published, consumers need a deterministic way to determine whether a release is compatible, governed, and safe to use. ## 3. Primary buyers and users @@ -18,7 +18,7 @@ Enterprise teams repeatedly hand-build business glossaries, ontologies, metric d ## 4. Core job to be done -Given an enterprise source estate, produce a **reviewable semantic model proposal** in which every concept, relationship, constraint, dimension, measure, and physical mapping is linked to exact evidence and can be validated, rejected, reviewed, published, superseded, and reproduced. +Given an enterprise source estate, produce a **reviewable semantic model proposal** in which every concept, relationship, constraint, dimension, measure, and physical mapping is linked to exact evidence and can be validated, rejected, reviewed, published, superseded, reproduced, and then safely admitted by downstream clients through a stable public contract. ## 5. Functional requirements @@ -52,20 +52,30 @@ Support stable adapters for `semantic-data-portal`, `LineageWeave`, `context-gra ### FR-8 LLM assistance -All LLM-backed induction uses `contextual-orchestrator`. Model output is untrusted proposal data and may not skip deterministic validation or review. +All LLM-backed induction uses `contextual-orchestrator`. Model output is untrusted proposal data and may not skip deterministic validation or review. Optional future client matching/explanation also routes through this boundary and cannot silently promote a correspondence to authority. -## 6. First vertical slice +### FR-9 Client consumption -Relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation report -> reviewable proposal package. +A consuming product can inspect a versioned `semantic_release` offline and fail closed before authoritative use. The first Client slice requires stable release identity, contract and ontology versions, truth/publication state, declared SHA-256 digest identity, provenance references, and unique concept identifiers. Admission requires an explicitly supported contract version plus `Published` and `Authoritative` state. Consuming products retain their own tenant/purpose authorization and physical data/query execution. + +The current digest value object validates the declared `sha256:<64 hex>` identity shape. Cryptographic integrity is not claimed until a later verifier hashes the exact serialized artifact bytes and compares the result. + +## 6. First Generation ↔ Client vertical + +`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission -> consuming-product ACL/query boundary`. + +`ContextualWisdomLab/governance-risk-compliance` is the first reference source/client scenario, not a special-case algorithm. A shared golden fixture must exercise both Generation and Client without copying GRC truth into ConceptWeave or giving ConceptWeave direct GRC application-table access. ## 7. Non-goals for v0.1 - replacing `semantic-data-portal` as the enterprise catalog; +- owning downstream tenant/purpose authorization or physical query execution; - arbitrary write access to source systems; - automatic publication without review; - treating vector similarity as semantic truth; - copying every external ontology into one CWL namespace; - building a generic LLM gateway or browser crawler; +- claiming digest syntax validation is cryptographic byte verification; - claiming an emerging draft semantic-layer format is a stable standard. ## 8. Acceptance criteria for the first commercial candidate @@ -78,4 +88,6 @@ Relational schema snapshot -> observed tables/columns/foreign keys -> concept/re - cross-tenant access denial when tenancy is introduced; - malformed/hostile source contracts rejected with bounded resource use; - semantic-model release can be reproduced from source receipts and approved proposal receipts; +- consumer can validate release schema/version/governance state offline before authoritative use; +- exact serialized artifact digest verification exists before integrity is claimed; - buyer can inspect why each published artifact exists and which evidence supported it. diff --git a/docs/TRD.md b/docs/TRD.md index ad5e1415..d64a251f 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -10,15 +10,16 @@ ConceptWeave starts as a Rust-first modular monolith with explicit bounded conte 2. **Semantic Discovery** — evidence-bound candidate generation. 3. **Model Validation** — deterministic structural, ontology, constraint, and semantic-model validation. 4. **Governance & Publication** — review decisions, immutable releases, supersession. -5. **Interoperability** — import/export adapters and CWL anti-corruption layers. +5. **Client Consumption** — release admission, compatibility and future diff/match/resolve/query-plan contracts. +6. **Interoperability** — import/export adapters and CWL anti-corruption layers. -The Core Domain is **Semantic Model Engineering**, represented by the discovery-to-publication lifecycle. Identity, LLM routing, outbound web access, observability, and catalog consumption are external/generic responsibilities. +The Core Domain is **Semantic Model Engineering**, represented by the discovery-to-publication lifecycle. Client Consumption is a supporting subdomain that protects downstream consumers from incompatible or non-governed releases. Identity, LLM routing, outbound web access, observability, catalog/search and consuming-product authorization are external/generic responsibilities. ## 3. Dependency direction `domain <- application <- ports/contracts <- adapters <- delivery` -Domain code must not import web frameworks, databases, provider SDKs, LLM SDKs, or another CWL product's internals. +Client Consumption depends only on versioned public release/domain contracts. Domain and client code must not import web frameworks, databases, provider SDKs, LLM SDKs, generator-private adapters, or another CWL product's internals. ## 4. Source observation contract @@ -37,22 +38,40 @@ Every observed source will eventually carry at least: The initial Rust and JSON contracts cover candidate kind, truth status, publication state, and source evidence. Later revisions add ontology IRIs, language-tagged labels, relation endpoints, cardinality, units, measure expressions, physical mappings, confidence/evaluation receipts, and temporal validity without breaking v0.1 consumers. -## 6. LLM boundary +## 6. Semantic-release client contract -LLM calls go through `contextual-orchestrator`. The application sends bounded evidence/context and receives structured proposals. LLM output is never a database command, publication decision, validation result, or source-system mutation. Deterministic checks must be able to reject the output without another model call. +The first Rust Client Consumption slice and Draft 2020-12 JSON Schema define an immutable consumer-visible contract containing: -## 7. Standards strategy +- `release_id`; +- `contract_version`; +- `ontology_version`; +- truth and publication state; +- declared artifact digest identity; +- one or more provenance references; +- unique stable concept identifiers. + +`SemanticReleaseClient` supports deterministic offline admission for one explicit contract version. Authoritative use is rejected unless the release is both `Published` and `Authoritative`. Structural construction and client admission do not grant publication authority. + +`ReleaseDigest` currently validates only the declared `sha256:<64 hex>` identity syntax. A later integrity adapter must hash the exact serialized bytes and compare that digest before cryptographic integrity can be claimed. The serialized contract, compatibility rules and verifier remain versioned public boundaries. + +Future #3 work adds older-supported compatibility policy, supersession/staleness handling, release diff, deterministic resolve, research-backed match/alignment, explain and query-plan operations. LLM-assisted client operations are optional; deterministic admission remains available with no provider call. + +## 7. LLM boundary + +LLM calls go through `contextual-orchestrator`. The application sends bounded evidence/context and receives structured proposals. LLM output is never a database command, publication decision, validation result, source-system mutation, client authorization decision, or automatic authoritative alignment. Deterministic checks must be able to reject the output without another model call. + +## 8. Standards strategy Stable publication targets use stable recommendations first: RDF 1.1, OWL 2, SKOS, SHACL 1.0, JSON-LD 1.1, and PROV-O as applicable. RDF 1.2 and SHACL 1.2 are tracked as 2026 drafts/candidate work and are not silently treated as final standards. Apache Ossie (incubating; formerly OSI) is tracked as an emerging semantic-model exchange format for metrics, dimensions, relationships, and datasets. -## 8. Persistence +## 9. Persistence -No durable product database is claimed by the foundation slice. When persistence is introduced it must be PostgreSQL, 3NF by default, use descriptive two-or-more-word `snake_case` objects, preserve business/effective time separately from system-recorded time when facts vary over time, enforce tenant-scoped references, and use explicit migration ownership rather than runtime DDL races. +No durable product database is claimed by the current slices. When persistence is introduced it must be PostgreSQL, 3NF by default, use descriptive two-or-more-word `snake_case` objects, preserve business/effective time separately from system-recorded time when facts vary over time, enforce tenant-scoped references, and use explicit migration ownership rather than runtime DDL races. Published releases are immutable; correction creates a superseding release. Item-level UPSERT behavior must be explicit and idempotency-tested before any mutable pre-publication persistence is introduced. -## 9. Security +## 10. Security -Source artifacts are untrusted input. Adapters must enforce source size/type bounds, parser timeouts, archive/decompression limits, SSRF-safe outbound access where external retrieval exists, and prompt-injection isolation for LLM-assisted extraction. Credentials and raw secrets never become semantic evidence. +Source artifacts and release payloads are untrusted input. Adapters must enforce source size/type bounds, parser timeouts, archive/decompression limits, SSRF-safe outbound access where external retrieval exists, and prompt-injection isolation for LLM-assisted extraction. Credentials and raw secrets never become semantic evidence. Client admission validates governance/compatibility but does not replace consuming-product tenant/purpose authorization. -## 10. Evaluation +## 11. Evaluation -Evaluation must separate extraction recall, semantic correctness, structural correctness, ontology consistency, mapping accuracy, measure correctness, and governance outcomes. Model-judge scores may supplement but never replace deterministic golden fixtures and human-reviewed expert cases. +Evaluation must separate extraction recall, semantic correctness, structural correctness, ontology consistency, mapping accuracy, measure correctness, release compatibility/admission correctness, and governance outcomes. Model-judge scores may supplement but never replace deterministic golden fixtures and human-reviewed expert cases. Client matching later uses OAEI-style precision/recall/F1 and candidate-retrieval recall; release admission uses deterministic malformed/version/state/provenance/digest fixtures. diff --git a/docs/UBIQUITOUS_LANGUAGE.md b/docs/UBIQUITOUS_LANGUAGE.md index 0c1d0c25..c0d03a7d 100644 --- a/docs/UBIQUITOUS_LANGUAGE.md +++ b/docs/UBIQUITOUS_LANGUAGE.md @@ -4,15 +4,20 @@ | --- | --- | | Source Snapshot | Immutable revision of source evidence observed by ConceptWeave. | | Observation | Deterministically extracted fact from a Source Snapshot. | -| Evidence Reference | Stable source identity, digest, and location supporting a candidate. | +| Evidence Reference | Stable source identity, digest, and location supporting a candidate or release. | | Semantic Candidate | Evidence-bound proposal for a concept, relation, constraint, dimension, measure, or physical mapping. | | Semantic Model Proposal | Versioned collection of candidates presented for validation/review. | | Validation Report | Deterministic result describing structural or semantic contract validity; not a review decision. | | Review Decision | Authorized accept/reject decision over validated candidates or a model proposal. | -| Semantic Model Release | Immutable governed publication artifact. | +| Semantic Model Release | Immutable governed publication artifact consumed only through versioned public contracts. | +| Release Contract Version | Explicit version of the client-visible semantic-release schema/compatibility contract. | +| Release Digest | Declared `sha256:<64 hex>` digest identity. Syntax validation alone is not cryptographic verification of artifact bytes. | +| Client Admission | Deterministic decision that a release has a supported contract version and is Published + Authoritative; it does not grant downstream authorization. | +| Client Consumption | Supporting bounded context for release admission, compatibility, and future diff/match/resolve/explain/query-plan contracts. | | Truth Status | Epistemic classification: observed, inferred, proposed, authoritative, superseded, rejected. | | Publication State | Governance workflow state: draft, proposed, validated, reviewed, published, superseded, rejected. | | Physical Mapping | Mapping from a physical schema/API/event element to a semantic concept or field. | | Dimension | Governed categorical or temporal axis used to group/filter analytical facts. | | Measure | Governed calculation with explicit expression, grain, units, null semantics, and evidence. | | Semantic Steward | Authorized reviewer responsible for accepting or rejecting semantic meaning. | +| Consuming Product ACL | Downstream product boundary that retains tenant/purpose authorization and physical data/query execution after ConceptWeave client admission. | diff --git a/docs/UML.md b/docs/UML.md index a9559e7f..0f7d3423 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -18,7 +18,7 @@ stateDiagram-v2 Superseded --> [*] ``` -## Foundation sequence +## Generation -> publication -> client sequence ```mermaid sequenceDiagram @@ -28,6 +28,8 @@ sequenceDiagram participant Validator participant Steward participant Publisher + participant Client + participant Consumer as Consuming Product ACL Source->>Observation: immutable snapshot Observation->>Discovery: observations + evidence refs @@ -36,5 +38,24 @@ sequenceDiagram Validator->>Steward: validated proposal Steward->>Publisher: reviewed acceptance Publisher-->>Source: no source mutation - Publisher-->>Steward: immutable release receipt + Publisher-->>Client: immutable versioned semantic_release + Client->>Client: validate contract version + Published + Authoritative + Client-->>Consumer: admitted public release contract + Consumer->>Consumer: tenant/purpose authorization + physical query planning/execution ``` + +## Client admission decision + +```mermaid +flowchart TD + R[Semantic release] --> V{Supported contract version?} + V -- no --> X1[Reject: incompatible] + V -- yes --> P{Publication state = Published?} + P -- no --> X2[Reject: not published] + P -- yes --> T{Truth status = Authoritative?} + T -- no --> X3[Reject: not authoritative] + T -- yes --> A[Admit for downstream authorization] + A --> H[Future: hash exact serialized bytes and compare digest] +``` + +Client admission is not publication authority and is not downstream authorization. `ReleaseDigest` currently validates the declared digest identity syntax; the future hash step is required before cryptographic integrity is claimed. diff --git a/docs/adr/0004-semantic-release-client-boundary.md b/docs/adr/0004-semantic-release-client-boundary.md new file mode 100644 index 00000000..ae042e47 --- /dev/null +++ b/docs/adr/0004-semantic-release-client-boundary.md @@ -0,0 +1,65 @@ +# ADR 0004 — Semantic-release client boundary + +- **Status:** Accepted +- **Date:** 2026-09-02 +- **Decision owners:** ConceptWeave Governance & Publication and Client Consumption bounded contexts + +## Context + +Issue #3 requires downstream CWL products to consume governed ConceptWeave releases without importing generation internals. The foundation already separates candidate truth from publication state, but a buyer-facing workflow is incomplete until a consumer can reject an incompatible or non-governed release before it is used. + +A client contract must remain useful offline. LLM/provider availability, generator prompts, persistence state, and foreign application databases cannot be prerequisites for deterministic release admission. Conversely, client-side structural checks must not be confused with publication authority, consuming-product authorization, or cryptographic verification that has not actually occurred. + +## Decision + +Introduce **Client Consumption** as a supporting bounded context and `conceptweave-client` as its first Rust reference implementation. + +The initial versioned `semantic_release` public contract carries: + +- stable release identity; +- explicit contract and ontology/model versions; +- truth and publication state; +- a declared artifact digest identity; +- provenance references; +- unique stable concept identifiers. + +`SemanticReleaseClient` admits authoritative use only when the release contract version exactly matches the supported version and the release is both `Published` and `Authoritative`. The check is deterministic and performs no network, model, database, source-system, or consumer-authorization work. + +The public Draft 2020-12 JSON Schema mirrors the structural invariants. `ReleaseDigest` accepts only `sha256:<64 hex>` as the declared digest identity. This is **not** a cryptographic integrity claim: a separate future adapter must hash the exact serialized release bytes and compare that digest before integrity is established. + +The generation-to-client seam is a versioned public contract. Client code may use public domain value types such as `TruthStatus`, `PublicationState`, and `EvidenceReference`, but may not import generator-private classes, prompts, provider payloads, persistence tables, or orchestration state. + +Consuming products keep tenant/purpose authorization, business-domain truth, and physical query execution. ConceptWeave returns semantic contracts/query plans; it does not become a foreign product's data plane. + +LLM-assisted future `match`, ambiguity explanation, and candidate ranking operations must use `ContextualWisdomLab/contextual-orchestrator`. Their outputs remain candidate/evidence state. `validate`, contract compatibility, digest verification, publication-state checks, and authorization remain deterministic. + +## Consequences + +### Positive + +- consumers can fail closed before authoritative use without an LLM provider; +- stable release contracts prevent generator-private implementation leakage; +- truth/publication authority remains explicit across repository boundaries; +- digest syntax and actual integrity verification cannot be accidentally conflated; +- GRC and other downstream consumers can build ACLs against one stable seam. + +### Costs and deferred work + +- current compatibility is exact-version only; older-supported compatibility and deprecation policy remain #3 work; +- current digest value validates identity syntax only; exact serialized-byte hashing/signature verification remains required before integrity claims; +- release diff, supersession/staleness policy, match/resolve/explain/query-plan operations remain #3 work; +- language-neutral generated bindings remain deferred until the JSON contract is stable enough to justify them. + +## Alternatives rejected + +1. **Let consumers import generator internals.** Rejected because it couples downstream products to prompts/adapters/persistence and destroys the reuse boundary. +2. **Require an LLM call to decide release usability.** Rejected because compatibility, governance state, and integrity are deterministic security controls. +3. **Treat a well-shaped digest string as proof of artifact integrity.** Rejected because syntax validation does not hash bytes. +4. **Move downstream authorization into ConceptWeave.** Rejected because tenant/purpose authorization belongs to each consuming product and its identity/control plane. + +## Verification + +- Rust integration tests cover authoritative admission, unsupported versions, non-Published and non-Authoritative states, provenance/identity requirements, duplicate concepts, and digest syntax. +- Error-message tests keep failures actionable. +- JSON Schema fixtures cover valid release, published/non-authoritative rejection, duplicate concept rejection, and malformed digest rejection. +- Product CI validates both Rust and JSON contracts on the exact PR head. diff --git a/docs/adr/README.md b/docs/adr/README.md index 291702a3..e10d8131 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -3,3 +3,4 @@ - [ADR 0001 — Product and bounded-context boundary](0001-product-boundary.md) - [ADR 0002 — Evidence, truth, and publication lifecycle](0002-truth-publication-lifecycle.md) - [ADR 0003 — Standards and LLM engineering boundary](0003-standards-llm-boundary.md) +- [ADR 0004 — Semantic-release client boundary](0004-semantic-release-client-boundary.md) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index c99d8269..d484325e 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,23 +1,42 @@ # Product / Technical Gap Baseline -**Snapshot:** 2026-09-01 +**Snapshot:** 2026-09-02 ## Shipped on protected `main` -Only the repository bootstrap README exists before the foundation PR. No production capability is claimed. +Only the repository bootstrap README exists before the foundation PR. No production capability is claimed from protected `main` yet. -## Active foundation slice +## Active foundation slice — PR #1 -| Area | Status | Evidence / next action | -| --- | --- | --- | -| Product boundary | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. | -| Truth/publication lifecycle | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated -> Reviewed -> Published. Draft 2020-12 JSON Schema enforces candidate shape, non-blank evidence identities, and Published -> Authoritative consistency; lifecycle history/pre-Reviewed publication is not a JSON-Schema responsibility. A test-first regression currently requires Reviewed -> Published to fail if required evidence is absent before this slice can be merge-ready. | -| Rust baseline | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | -| Quality gate | ACTIVE_PR | Product workflow for fmt/clippy/tests/docs/coverage/Draft-2020-12 schema fixtures/lock/clean-tree; exact current-head hosted execution remains required. | -| Standards/research | ACTIVE_PR | Stable-vs-draft standards plus paper-by-paper Generation/Client/Bridge/cross-cutting capability and evaluation traceability. | -| Security/test/operability | ACTIVE_PR | Baselines added; published semantic truth is specified as immutable with correction by superseding release; no production service claimed. | +| Area | Owner | Status | Evidence / action / next verification | +| --- | --- | --- | --- | +| Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against the exact PR #1 head before merge. | +| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated -> Reviewed -> Published. Draft 2020-12 candidate schema enforces candidate shape and Published -> Authoritative consistency. | +| Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | +| Quality gate | ConceptWeave | ACTIVE_PR | Product workflow checks exact checkout, fmt, Clippy, tests, docs, exact owned coverage, JSON contracts, lock freshness, and clean tree. Repository-owned Product was green on foundation head `5cd7d1de742fe34aa99900641cc8b124e7c65f9e`; predecessor results never transfer to a newer head. | +| Standards/research | ConceptWeave | ACTIVE_PR | Stable-vs-draft standards plus paper-by-paper Generation/Client/Bridge/cross-cutting capability and evaluation traceability. | +| Security/test/operability | ConceptWeave | ACTIVE_PR | Baselines added; published semantic truth is immutable with correction by superseding release; no production service claimed. | -## P0 product gaps after foundation +## Active Client Consumption slice — PR #5 / Issue #3 + +PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. The canonical exact head is the live GitHub PR head; it is not duplicated as a self-referential constant in this file because editing this baseline itself changes that SHA. Check results are valid only for the unchanged live PR head. + +| Gap | Owner | Status | Evidence | Action | Next verification | +| --- | --- | --- | --- | --- | --- | +| Offline release admission | Client Consumption | IMPLEMENTED_ACTIVE_PR | Test-first commits define and implement `SemanticReleaseClient`; authoritative use requires exact supported contract version + Published + Authoritative. | Keep deterministic and provider-independent. | Exact-head Rust tests/Clippy/docs/coverage. | +| Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_ACTIVE_PR | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance, unique concept IDs. | Stabilize compatibility/deprecation semantics before generated language bindings. | Exact-head AJV + Rust contract parity. | +| Declared digest identity | Client Consumption | PARTIAL | `ReleaseDigest` accepts only `sha256:<64 hex>`. | Add exact serialized-byte hashing and digest comparison before integrity is claimed; later add signature/provenance verification where release design warrants it. | Golden artifact mutation/tamper fixtures. | +| Release compatibility | Client Consumption | PARTIAL | Exact-version admission exists. | Add supported-version range/deprecation policy, malformed/unknown/older-supported/superseded cases. | Compatibility matrix fixtures. | +| Release diff / stale handling | Client Consumption | GAP | Research traceability maps OM4OV to explicit version-change semantics. | Implement typed `diff` and supersession/staleness outcomes without treating ordinary ontology matching as versioning. | Added/removed/changed entity golden fixtures. | +| Match / resolve / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research register defines retrieve/filter/match constraints. | Implement deterministic candidate retrieval first; optional LLM work only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | +| Query-plan contract | Client Consumption | GAP | Issue #3 requires plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | +| Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave client performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution in consuming products. | Cross-tenant/purpose denial tests in each consumer. | + +## Causal control-plane gap + +Organization-required Security/SAST runner admission is owned by `ContextualWisdomLab/.github`, not by a leaf ConceptWeave source workaround. Central PR #1618 pins the affected required workflows from floating `ubuntu-latest` to explicit `ubuntu-24.04` with a regression contract and has demonstrated Security Scan and SAST Semgrep success on its own exact head. ConceptWeave must continue to require fresh exact-head central evidence after that control-plane repair lands; no predecessor result, no-op retrigger, or governance bypass is acceptable. + +## Remaining P0 product gaps 1. **Source Observation vertical** — relational schema snapshot contract, real PostgreSQL introspection adapter, immutable digest/location receipts, hostile-input bounds. 2. **Ontology induction** — deterministic observations plus contextual-orchestrator structured candidate generation for concepts, taxonomy, and non-taxonomic relations. @@ -26,16 +45,20 @@ Only the repository bootstrap README exists before the foundation PR. No product 5. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, releases, transactional outbox, bitemporal history where applicable. 6. **Review workflow** — Keyverse tenant/role/purpose context, steward review, maker-checker where required, stale decision protection, immutable publication receipt. 7. **Publication adapters** — OWL/RDFS/SKOS/SHACL/JSON-LD and version-bound Apache Ossie semantic-model export. -8. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC, and EA through published contracts only. -9. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility, multilingual cases. -10. **Secure external research** — SearXNG discovery and safe source fetch through the correct CWL egress boundary for ontology grounding, never search snippets as truth. -11. **Observability** — shared CWL OpenTelemetry import/bootstrap contract, detailed structured logs, SIEM security-event projection where applicable. -12. **Release** — SBOM, provenance, signed artifacts, migration/backup/restore evidence, versioned changelog, protected release pipeline. +8. **Client completion** — byte-level integrity verification, compatibility/deprecation, diff/stale handling, match/resolve/explain/query-plan, generated bindings only when contract stability warrants them. +9. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC, and EA through published contracts only. +10. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility, multilingual cases. +11. **Secure external research** — SearXNG discovery and safe source fetch through the correct CWL egress boundary for ontology grounding, never search snippets as truth. +12. **Observability** — shared CWL OpenTelemetry import/bootstrap contract, detailed structured logs, SIEM security-event projection where applicable. +13. **Release** — SBOM, provenance, signed artifacts, migration/backup/restore evidence, versioned changelog, protected release pipeline. -## DDD fitness gaps +## DDD fitness gaps and invariants - No generic `utils/helpers/services/common` domain buckets are permitted. - Adapters must remain outside `conceptweave-domain`. +- Client Consumption may consume versioned public contracts but not generator-private implementation. - Foreign product DTOs require Anti-Corruption Layers. - `semantic-data-portal` must not become ConceptWeave persistence, and ConceptWeave must not become an SDP clone. +- Consuming-product authorization/query execution stays downstream; ConceptWeave does not own foreign application tables. - External forks/tools can be optional adapters but are not CWL-owned product authorities. +- Future persistence uses descriptive two-or-more-word `snake_case` objects, 3NF by default, explicit item-level UPSERT/idempotency contracts, and immutable published releases. From eaed92fa21fa0f10d2d7522a278a87f37ea56b47 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:39:05 +0900 Subject: [PATCH 08/67] test(client): require release metadata value object --- .../tests/release_validation.rs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/crates/conceptweave-client/tests/release_validation.rs b/crates/conceptweave-client/tests/release_validation.rs index 2345b0e6..82045f01 100644 --- a/crates/conceptweave-client/tests/release_validation.rs +++ b/crates/conceptweave-client/tests/release_validation.rs @@ -1,5 +1,5 @@ use conceptweave_client::{ - ReleaseContractError, ReleaseDigest, SemanticRelease, SemanticReleaseClient, + ReleaseContractError, ReleaseDigest, ReleaseMetadata, SemanticRelease, SemanticReleaseClient, }; use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; @@ -17,15 +17,22 @@ fn digest() -> ReleaseDigest { .unwrap() } +fn metadata(contract_version: &str) -> ReleaseMetadata { + ReleaseMetadata::new( + "semantic-release-grc-2026-09-01", + contract_version, + "grc-ontology-2026-09", + ) + .unwrap() +} + fn release( contract_version: &str, truth_status: TruthStatus, publication_state: PublicationState, ) -> SemanticRelease { SemanticRelease::new( - "semantic-release-grc-2026-09-01", - contract_version, - "grc-ontology-2026-09", + metadata(contract_version), truth_status, publication_state, digest(), @@ -107,32 +114,29 @@ fn client_rejects_unsupported_contract_version_before_use() { } #[test] -fn release_requires_identity_versions_provenance_and_unique_non_blank_concepts() { +fn metadata_requires_non_blank_release_contract_and_ontology_versions() { for (release_id, contract_version, ontology_version, expected_field) in [ (" ", "1.0.0", "ontology-1", "release_id"), ("release-1", " ", "ontology-1", "contract_version"), ("release-1", "1.0.0", " ", "ontology_version"), ] { assert_eq!( - SemanticRelease::new( - release_id, - contract_version, - ontology_version, - TruthStatus::Authoritative, - PublicationState::Published, - digest(), - vec![evidence()], - vec!["concept.one".to_string()], - ), + ReleaseMetadata::new(release_id, contract_version, ontology_version), Err(ReleaseContractError::EmptyField(expected_field)) ); } + let metadata = ReleaseMetadata::new("release-1", "1.0.0", "ontology-1").unwrap(); + assert_eq!(metadata.release_id(), "release-1"); + assert_eq!(metadata.contract_version(), "1.0.0"); + assert_eq!(metadata.ontology_version(), "ontology-1"); +} + +#[test] +fn release_requires_provenance_and_unique_non_blank_concepts() { assert_eq!( SemanticRelease::new( - "release-1", - "1.0.0", - "ontology-1", + metadata("1.0.0"), TruthStatus::Authoritative, PublicationState::Published, digest(), @@ -144,9 +148,7 @@ fn release_requires_identity_versions_provenance_and_unique_non_blank_concepts() assert_eq!( SemanticRelease::new( - "release-1", - "1.0.0", - "ontology-1", + metadata("1.0.0"), TruthStatus::Authoritative, PublicationState::Published, digest(), @@ -158,9 +160,7 @@ fn release_requires_identity_versions_provenance_and_unique_non_blank_concepts() assert_eq!( SemanticRelease::new( - "release-1", - "1.0.0", - "ontology-1", + metadata("1.0.0"), TruthStatus::Authoritative, PublicationState::Published, digest(), From 42455fa5529d376dd8eeb035a9f7e8086bb42fa2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:39:51 +0900 Subject: [PATCH 09/67] refactor(client): model release identity as value object --- crates/conceptweave-client/src/lib.rs | 84 +++++++++++++++++++-------- 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 03f1e201..ae840cf7 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -41,12 +41,58 @@ impl ReleaseDigest { } } -/// Immutable client-visible metadata required to admit a semantic release. +/// Stable identity and version metadata for one semantic release. +/// +/// Keeping these related identity fields in one value object prevents call sites +/// from relying on a long positional constructor and makes later compatibility +/// policy explicit without exposing mutable release internals. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct SemanticRelease { +pub struct ReleaseMetadata { release_id: String, contract_version: String, ontology_version: String, +} + +impl ReleaseMetadata { + /// Creates validated stable release, contract, and ontology identities. + pub fn new( + release_id: impl Into, + contract_version: impl Into, + ontology_version: impl Into, + ) -> Result { + let release_id = release_id.into(); + let contract_version = contract_version.into(); + let ontology_version = ontology_version.into(); + require_non_blank(&release_id, "release_id")?; + require_non_blank(&contract_version, "contract_version")?; + require_non_blank(&ontology_version, "ontology_version")?; + Ok(Self { + release_id, + contract_version, + ontology_version, + }) + } + + /// Returns the stable semantic-release identity. + pub fn release_id(&self) -> &str { + &self.release_id + } + + /// Returns the client contract version encoded by the release. + pub fn contract_version(&self) -> &str { + &self.contract_version + } + + /// Returns the ontology/model version encoded by the release. + pub fn ontology_version(&self) -> &str { + &self.ontology_version + } +} + +/// Immutable client-visible metadata required to admit a semantic release. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SemanticRelease { + metadata: ReleaseMetadata, truth_status: TruthStatus, publication_state: PublicationState, artifact_digest: ReleaseDigest, @@ -57,28 +103,18 @@ pub struct SemanticRelease { impl SemanticRelease { /// Constructs a structurally valid semantic release contract. /// - /// Construction validates stable identity, version metadata, provenance and - /// concept identity uniqueness. Whether the release is safe for authoritative - /// use is a separate client-policy decision performed by - /// [`SemanticReleaseClient::validate_for_authoritative_use`]. - #[allow(clippy::too_many_arguments)] + /// Construction validates provenance and concept identity uniqueness while + /// [`ReleaseMetadata`] validates stable release/version identities. Whether + /// the release is safe for authoritative use is a separate client-policy + /// decision performed by [`SemanticReleaseClient::validate_for_authoritative_use`]. pub fn new( - release_id: impl Into, - contract_version: impl Into, - ontology_version: impl Into, + metadata: ReleaseMetadata, truth_status: TruthStatus, publication_state: PublicationState, artifact_digest: ReleaseDigest, provenance: Vec, concept_ids: Vec, ) -> Result { - let release_id = release_id.into(); - let contract_version = contract_version.into(); - let ontology_version = ontology_version.into(); - - require_non_blank(&release_id, "release_id")?; - require_non_blank(&contract_version, "contract_version")?; - require_non_blank(&ontology_version, "ontology_version")?; if provenance.is_empty() { return Err(ReleaseContractError::MissingProvenance); } @@ -94,9 +130,7 @@ impl SemanticRelease { } Ok(Self { - release_id, - contract_version, - ontology_version, + metadata, truth_status, publication_state, artifact_digest, @@ -107,17 +141,17 @@ impl SemanticRelease { /// Returns the stable semantic-release identity. pub fn release_id(&self) -> &str { - &self.release_id + self.metadata.release_id() } /// Returns the client contract version encoded by this release. pub fn contract_version(&self) -> &str { - &self.contract_version + self.metadata.contract_version() } /// Returns the ontology/model version carried by this release. pub fn ontology_version(&self) -> &str { - &self.ontology_version + self.metadata.ontology_version() } /// Returns the release truth status. @@ -181,10 +215,10 @@ impl SemanticReleaseClient { &self, release: &SemanticRelease, ) -> Result<(), ReleaseContractError> { - if release.contract_version != self.supported_contract_version { + if release.contract_version() != self.supported_contract_version { return Err(ReleaseContractError::UnsupportedContractVersion { expected: self.supported_contract_version.clone(), - actual: release.contract_version.clone(), + actual: release.contract_version().to_string(), }); } if release.publication_state != PublicationState::Published { From b48eab71ecac3a7e0d41b8841ba02214226ffbea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:50:25 +0900 Subject: [PATCH 10/67] docs(client): reconcile central security evidence --- docs/product-technical-gap-baseline.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index d484325e..6a597d35 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -11,11 +11,11 @@ Only the repository bootstrap README exists before the foundation PR. No product | Area | Owner | Status | Evidence / action / next verification | | --- | --- | --- | --- | | Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against the exact PR #1 head before merge. | -| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated -> Reviewed -> Published. Draft 2020-12 candidate schema enforces candidate shape and Published -> Authoritative consistency. | +| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated while the public transition API fails closed at steward-reviewed/publication boundaries; Draft 2020-12 candidate schema enforces public candidate shape and Published -> Authoritative consistency. | | Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | -| Quality gate | ConceptWeave | ACTIVE_PR | Product workflow checks exact checkout, fmt, Clippy, tests, docs, exact owned coverage, JSON contracts, lock freshness, and clean tree. Repository-owned Product was green on foundation head `5cd7d1de742fe34aa99900641cc8b124e7c65f9e`; predecessor results never transfer to a newer head. | +| Quality gate | ConceptWeave | ACTIVE_PR | Product workflow checks exact checkout, CI contract, fmt, Clippy, tests, rustdoc, exact owned 100% line/function/region/source-branch coverage, JSON contracts, lock freshness, and clean tree. Foundation PR #1 current exact head must supply fresh evidence; predecessor evidence never transfers. | | Standards/research | ConceptWeave | ACTIVE_PR | Stable-vs-draft standards plus paper-by-paper Generation/Client/Bridge/cross-cutting capability and evaluation traceability. | -| Security/test/operability | ConceptWeave | ACTIVE_PR | Baselines added; published semantic truth is immutable with correction by superseding release; no production service claimed. | +| Security/test/operability | ConceptWeave + central `.github` security workflow | ACTIVE_PR / CONTROL_PLANE_BLOCKED | Product and SAST execute on the exact foundation head. Security Scan is fail-closed because Dependency Review authoritative comparison evidence is currently unavailable; sibling scanners do not substitute. | ## Active Client Consumption slice — PR #5 / Issue #3 @@ -32,9 +32,11 @@ PR #5 is intentionally stacked on PR #1 because the client reuses only the found | Query-plan contract | Client Consumption | GAP | Issue #3 requires plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | | Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave client performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution in consuming products. | Cross-tenant/purpose denial tests in each consumer. | -## Causal control-plane gap +## Central control-plane evidence -Organization-required Security/SAST runner admission is owned by `ContextualWisdomLab/.github`, not by a leaf ConceptWeave source workaround. Central PR #1618 pins the affected required workflows from floating `ubuntu-latest` to explicit `ubuntu-24.04` with a regression contract and has demonstrated Security Scan and SAST Semgrep success on its own exact head. ConceptWeave must continue to require fresh exact-head central evidence after that control-plane repair lands; no predecessor result, no-op retrigger, or governance bypass is acceptable. +The runner-admission defect was repaired at the owning central boundary: `ContextualWisdomLab/.github` PR #1618 merged after changing the affected organization-required Security Scan/SAST runner selectors from the observed-starved floating `ubuntu-latest` to explicit `ubuntu-24.04` while retaining exact-head validation, scanner logic, permissions, thresholds and immutable action pins. + +Fresh foundation PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` proves the runner repair reached this repository: Product run `33527150325` and SAST run `33527150417` are terminal success, and Security Scan run `33527150445` acquired an Ubuntu 24.04 runner and checked out the exact head. Security then failed at a different central evidence boundary: dependency-review job `99920784712` received HTTP `403` with curl exit `0` from the exact dependency-graph comparison `main@f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425...bba351b77bf5f1ab5cfd55979fbb2bd158f78b81`. The fail-closed workflow correctly did not run the pinned Dependency Review action. Central `.github#810` owns this availability/configuration incident; ConceptWeave must not weaken the gate or substitute OSV/Trivy/Scorecard. GREEN requires an unchanged public non-fork head where the exact comparison returns HTTP 200 and the pinned Dependency Review action actually executes terminally. ## Remaining P0 product gaps From 41629bd0f24c4cbe21b3d14dcec645f980e921b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 00:55:20 +0900 Subject: [PATCH 11/67] test(client): require canonical lowercase release digest --- .github/workflows/product.yml | 5 +++++ ...emantic-release.invalid-uppercase-digest.json | 16 ++++++++++++++++ .../tests/digest_canonicalization.rs | 11 +++++++++++ 3 files changed, 32 insertions(+) create mode 100644 contracts/fixtures/semantic-release.invalid-uppercase-digest.json create mode 100644 crates/conceptweave-client/tests/digest_canonicalization.rs diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index 47d28405..c375203d 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -104,6 +104,11 @@ jobs: -s contracts/semantic-release.schema.json \ -d contracts/fixtures/semantic-release.invalid-digest.json \ --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-uppercase-digest.json \ + --invalid - name: Lockfile freshness run: | diff --git a/contracts/fixtures/semantic-release.invalid-uppercase-digest.json b/contracts/fixtures/semantic-release.invalid-uppercase-digest.json new file mode 100644 index 00000000..1e9a1a04 --- /dev/null +++ b/contracts/fixtures/semantic-release.invalid-uppercase-digest.json @@ -0,0 +1,16 @@ +{ + "release_id": "semantic-release-grc-2026-09-01", + "contract_version": "1.0.0", + "ontology_version": "grc-ontology-2026-09", + "truth_status": "authoritative", + "publication_state": "published", + "artifact_digest": "sha256:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "provenance": [ + { + "source_id": "snapshot:grc-schema-2026-09-01", + "source_digest": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "location": "public.control_evidence.control_identifier" + } + ], + "concept_ids": ["control.evidence", "control.owner"] +} diff --git a/crates/conceptweave-client/tests/digest_canonicalization.rs b/crates/conceptweave-client/tests/digest_canonicalization.rs new file mode 100644 index 00000000..449268ba --- /dev/null +++ b/crates/conceptweave-client/tests/digest_canonicalization.rs @@ -0,0 +1,11 @@ +use conceptweave_client::{ReleaseContractError, ReleaseDigest}; + +#[test] +fn uppercase_sha256_digest_identity_is_rejected() { + let uppercase_digest = format!("sha256:{}", "A".repeat(64)); + + assert_eq!( + ReleaseDigest::new(uppercase_digest), + Err(ReleaseContractError::InvalidDigest) + ); +} From 216056c2adc81f41002e4fbb60124a402f2d193e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:03:25 +0900 Subject: [PATCH 12/67] style(client): format digest contract RED --- crates/conceptweave-client/src/lib.rs | 9 ++------- .../tests/release_validation.rs | 20 ++++++++----------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index ae840cf7..9cc1ff83 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -123,9 +123,7 @@ impl SemanticRelease { for concept_id in &concept_ids { require_non_blank(concept_id, "concept_id")?; if !unique_concepts.insert(concept_id.as_str()) { - return Err(ReleaseContractError::DuplicateConceptId( - concept_id.clone(), - )); + return Err(ReleaseContractError::DuplicateConceptId(concept_id.clone())); } } @@ -192,10 +190,7 @@ impl SemanticReleaseClient { supported_contract_version: impl Into, ) -> Result { let supported_contract_version = supported_contract_version.into(); - require_non_blank( - &supported_contract_version, - "supported_contract_version", - )?; + require_non_blank(&supported_contract_version, "supported_contract_version")?; Ok(Self { supported_contract_version, }) diff --git a/crates/conceptweave-client/tests/release_validation.rs b/crates/conceptweave-client/tests/release_validation.rs index 82045f01..4aa80ef3 100644 --- a/crates/conceptweave-client/tests/release_validation.rs +++ b/crates/conceptweave-client/tests/release_validation.rs @@ -70,11 +70,7 @@ fn authoritative_published_release_is_admitted_offline() { fn client_fails_closed_on_unpublished_or_non_authoritative_release() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let reviewed = release( - "1.0.0", - TruthStatus::Inferred, - PublicationState::Reviewed, - ); + let reviewed = release("1.0.0", TruthStatus::Inferred, PublicationState::Reviewed); assert_eq!( client.validate_for_authoritative_use(&reviewed), Err(ReleaseContractError::ReleaseNotPublished { @@ -82,11 +78,7 @@ fn client_fails_closed_on_unpublished_or_non_authoritative_release() { }) ); - let wrong_truth = release( - "1.0.0", - TruthStatus::Proposed, - PublicationState::Published, - ); + let wrong_truth = release("1.0.0", TruthStatus::Proposed, PublicationState::Published); assert_eq!( client.validate_for_authoritative_use(&wrong_truth), Err(ReleaseContractError::ReleaseNotAuthoritative { @@ -184,7 +176,9 @@ fn digest_contract_rejects_non_sha256_and_malformed_hex() { Err(ReleaseContractError::InvalidDigest) ); assert_eq!( - ReleaseDigest::new("sha256:gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"), + ReleaseDigest::new( + "sha256:gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg" + ), Err(ReleaseContractError::InvalidDigest) ); } @@ -193,6 +187,8 @@ fn digest_contract_rejects_non_sha256_and_malformed_hex() { fn client_requires_non_blank_supported_contract_version() { assert_eq!( SemanticReleaseClient::new(" "), - Err(ReleaseContractError::EmptyField("supported_contract_version")) + Err(ReleaseContractError::EmptyField( + "supported_contract_version" + )) ); } From f71befbd97b8401551a9dad061e9c562c7b78d36 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:11:14 +0900 Subject: [PATCH 13/67] fix(client): canonicalize lowercase release digest identity --- contracts/semantic-release.schema.json | 2 +- crates/conceptweave-client/src/lib.rs | 19 +++++++++++++------ .../tests/error_messages.rs | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/contracts/semantic-release.schema.json b/contracts/semantic-release.schema.json index 52c2d41d..ebea6ff0 100644 --- a/contracts/semantic-release.schema.json +++ b/contracts/semantic-release.schema.json @@ -53,7 +53,7 @@ }, "artifact_digest": { "type": "string", - "pattern": "^sha256:[0-9A-Fa-f]{64}$" + "pattern": "^sha256:[0-9a-f]{64}$" }, "provenance": { "type": "array", diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 9cc1ff83..a66b89e2 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -13,9 +13,10 @@ use std::collections::BTreeSet; /// A validated content-digest identity carried by a semantic release. /// -/// The current contract accepts only the explicit `sha256:<64 hex>` shape. This -/// value object validates digest identity syntax; byte-for-byte cryptographic -/// re-hashing belongs to the serialized-artifact verification adapter. +/// The current contract accepts only the canonical `sha256:<64 lowercase hex>` +/// shape. This value object validates digest identity syntax; byte-for-byte +/// cryptographic re-hashing belongs to the serialized-artifact verification +/// adapter. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ReleaseDigest(String); @@ -29,7 +30,10 @@ impl ReleaseDigest { if hex.len() != 64 { return Err(ReleaseContractError::InvalidDigest); } - if !hex.bytes().all(|byte| byte.is_ascii_hexdigit()) { + if !hex + .bytes() + .all(|byte| matches!(byte, b'0'..=b'9' | b'a'..=b'f')) + { return Err(ReleaseContractError::InvalidDigest); } Ok(Self(value)) @@ -242,7 +246,7 @@ fn require_non_blank(value: &str, field: &'static str) -> Result<(), ReleaseCont pub enum ReleaseContractError { /// A required stable identity or version field was blank. EmptyField(&'static str), - /// The declared release digest is not `sha256:<64 hex>`. + /// The declared release digest is not canonical `sha256:<64 lowercase hex>`. InvalidDigest, /// The release carries no provenance evidence. MissingProvenance, @@ -271,7 +275,10 @@ impl fmt::Display for ReleaseContractError { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::EmptyField(field) => write!(formatter, "required field `{field}` is blank"), - Self::InvalidDigest => write!(formatter, "release digest must use sha256:<64 hex>"), + Self::InvalidDigest => write!( + formatter, + "release digest must use sha256:<64 lowercase hex>" + ), Self::MissingProvenance => { write!(formatter, "semantic releases require provenance evidence") } diff --git a/crates/conceptweave-client/tests/error_messages.rs b/crates/conceptweave-client/tests/error_messages.rs index c5ce1e5c..d366cf52 100644 --- a/crates/conceptweave-client/tests/error_messages.rs +++ b/crates/conceptweave-client/tests/error_messages.rs @@ -10,7 +10,7 @@ fn contract_errors_explain_the_failed_admission_invariant() { ), ( ReleaseContractError::InvalidDigest, - "release digest must use sha256:<64 hex>".to_string(), + "release digest must use sha256:<64 lowercase hex>".to_string(), ), ( ReleaseContractError::MissingProvenance, From 09f8ffb3003656638c1d08d0f46074c3143fdcf6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:23:23 +0900 Subject: [PATCH 14/67] test(client): specify semantic release diff contract --- .../conceptweave-client/tests/release_diff.rs | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 crates/conceptweave-client/tests/release_diff.rs diff --git a/crates/conceptweave-client/tests/release_diff.rs b/crates/conceptweave-client/tests/release_diff.rs new file mode 100644 index 00000000..22303a29 --- /dev/null +++ b/crates/conceptweave-client/tests/release_diff.rs @@ -0,0 +1,76 @@ +use conceptweave_client::{ + ReleaseContractError, ReleaseDigest, ReleaseMetadata, SemanticRelease, SemanticReleaseClient, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_evidence.control_identifier", + ) + .unwrap() +} + +fn release(release_id: &str, concept_ids: &[&str], state: PublicationState) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new(release_id, "1.0.0", "grc-ontology-2026-09").unwrap(), + if state == PublicationState::Published { + TruthStatus::Authoritative + } else { + TruthStatus::Inferred + }, + state, + ReleaseDigest::new( + "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + ) + .unwrap(), + vec![evidence()], + concept_ids.iter().map(|value| (*value).to_string()).collect(), + ) + .unwrap() +} + +#[test] +fn release_diff_reports_deterministic_added_and_removed_concepts() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let previous = release( + "semantic-release-grc-v1", + &["control.evidence", "control.owner"], + PublicationState::Published, + ); + let current = release( + "semantic-release-grc-v2", + &["control.effectiveness", "control.evidence"], + PublicationState::Published, + ); + + let diff = client.diff(&previous, ¤t).unwrap(); + + assert_eq!(diff.previous_release_id(), "semantic-release-grc-v1"); + assert_eq!(diff.current_release_id(), "semantic-release-grc-v2"); + assert_eq!(diff.added_concept_ids(), ["control.effectiveness"]); + assert_eq!(diff.removed_concept_ids(), ["control.owner"]); +} + +#[test] +fn release_diff_fails_closed_when_either_release_is_not_admissible() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let previous = release( + "semantic-release-grc-v1", + &["control.evidence"], + PublicationState::Published, + ); + let reviewed = release( + "semantic-release-grc-v2", + &["control.effectiveness"], + PublicationState::Reviewed, + ); + + assert_eq!( + client.diff(&previous, &reviewed), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }) + ); +} From 5776e2cb56bf91070c0c1e5c04e3e3364cd8e5a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:26:01 +0900 Subject: [PATCH 15/67] test(client): format semantic release diff RED --- crates/conceptweave-client/tests/release_diff.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/conceptweave-client/tests/release_diff.rs b/crates/conceptweave-client/tests/release_diff.rs index 22303a29..509688f0 100644 --- a/crates/conceptweave-client/tests/release_diff.rs +++ b/crates/conceptweave-client/tests/release_diff.rs @@ -26,7 +26,10 @@ fn release(release_id: &str, concept_ids: &[&str], state: PublicationState) -> S ) .unwrap(), vec![evidence()], - concept_ids.iter().map(|value| (*value).to_string()).collect(), + concept_ids + .iter() + .map(|value| (*value).to_string()) + .collect(), ) .unwrap() } From ab747eca3aedff30288b178f2bfa381b8fef65b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:31:41 +0900 Subject: [PATCH 16/67] feat(client): add deterministic semantic release diff --- crates/conceptweave-client/src/lib.rs | 71 +++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index a66b89e2..bf20a1ab 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -182,6 +182,41 @@ impl SemanticRelease { } } +/// Deterministic concept-level change between two admitted semantic releases. +/// +/// This value reports only public semantic-contract differences. It does not +/// authorize downstream queries, mutate either release, or infer business-domain +/// consequences for a consuming product. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SemanticReleaseDiff { + previous_release_id: String, + current_release_id: String, + added_concept_ids: Vec, + removed_concept_ids: Vec, +} + +impl SemanticReleaseDiff { + /// Returns the stable identity of the earlier release. + pub fn previous_release_id(&self) -> &str { + &self.previous_release_id + } + + /// Returns the stable identity of the later release. + pub fn current_release_id(&self) -> &str { + &self.current_release_id + } + + /// Returns concept identities present only in the later release. + pub fn added_concept_ids(&self) -> &[String] { + &self.added_concept_ids + } + + /// Returns concept identities present only in the earlier release. + pub fn removed_concept_ids(&self) -> &[String] { + &self.removed_concept_ids + } +} + /// Offline admission policy for one supported semantic-release contract version. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SemanticReleaseClient { @@ -232,6 +267,42 @@ impl SemanticReleaseClient { } Ok(()) } + + /// Compares two admitted releases and reports deterministic concept changes. + /// + /// Both releases pass the same authoritative-use admission gate before any + /// difference is exposed. This prevents diff inspection from becoming a + /// compatibility or publication-state bypass. Concept identifiers are sorted + /// deterministically so the result is reproducible offline. + pub fn diff( + &self, + previous: &SemanticRelease, + current: &SemanticRelease, + ) -> Result { + self.validate_for_authoritative_use(previous)?; + self.validate_for_authoritative_use(current)?; + + let previous_concepts: BTreeSet<&str> = + previous.concept_ids().iter().map(String::as_str).collect(); + let current_concepts: BTreeSet<&str> = + current.concept_ids().iter().map(String::as_str).collect(); + + let added_concept_ids = current_concepts + .difference(&previous_concepts) + .map(|concept_id| (*concept_id).to_string()) + .collect(); + let removed_concept_ids = previous_concepts + .difference(¤t_concepts) + .map(|concept_id| (*concept_id).to_string()) + .collect(); + + Ok(SemanticReleaseDiff { + previous_release_id: previous.release_id().to_string(), + current_release_id: current.release_id().to_string(), + added_concept_ids, + removed_concept_ids, + }) + } } fn require_non_blank(value: &str, field: &'static str) -> Result<(), ReleaseContractError> { From 7af0bc25fc1226d777f9b365e980f42a30e23d6b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:34:59 +0900 Subject: [PATCH 17/67] test(client): cover both release diff admission failures --- .../conceptweave-client/tests/release_diff.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/conceptweave-client/tests/release_diff.rs b/crates/conceptweave-client/tests/release_diff.rs index 509688f0..7abf6d5e 100644 --- a/crates/conceptweave-client/tests/release_diff.rs +++ b/crates/conceptweave-client/tests/release_diff.rs @@ -59,21 +59,25 @@ fn release_diff_reports_deterministic_added_and_removed_concepts() { #[test] fn release_diff_fails_closed_when_either_release_is_not_admissible() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let previous = release( - "semantic-release-grc-v1", + let published = release( + "semantic-release-grc-published", &["control.evidence"], PublicationState::Published, ); - let reviewed = release( - "semantic-release-grc-v2", + let reviewed_previous = release( + "semantic-release-grc-reviewed-previous", + &["control.owner"], + PublicationState::Reviewed, + ); + let reviewed_current = release( + "semantic-release-grc-reviewed-current", &["control.effectiveness"], PublicationState::Reviewed, ); + let expected = Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }); - assert_eq!( - client.diff(&previous, &reviewed), - Err(ReleaseContractError::ReleaseNotPublished { - actual: PublicationState::Reviewed, - }) - ); + assert_eq!(client.diff(&reviewed_previous, &published), expected); + assert_eq!(client.diff(&published, &reviewed_current), expected); } From c8c7ad05e0c7fb9b5f60645f6a8b0410b509a08e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:38:24 +0900 Subject: [PATCH 18/67] docs(client): record admitted release diff contract --- CHANGELOG.md | 2 ++ docs/PRD.md | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7705b75e..2225cb5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to ConceptWeave are documented here. - Fail-closed Draft -> Proposed -> Validated -> Reviewed -> Published lifecycle with explicit rejection and supersession. - Draft 2020-12 JSON Schema for the semantic-candidate public contract. - Rust-first `conceptweave-client` supporting subdomain with deterministic offline semantic-release admission by contract version, publication state, truth status, provenance, stable concept identity, and declared SHA-256 digest identity. +- Deterministic offline semantic-release diff that first applies the same authoritative-use admission policy, then reports stable previous/current release identity and sorted added/removed concept identifiers without network or model calls. - Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. - Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. @@ -18,5 +19,6 @@ All notable changes to ConceptWeave are documented here. - Model-generated semantics remain non-authoritative until deterministic validation and authorized review. - Client authoritative-use admission rejects incompatible, unpublished, or non-authoritative releases without requiring a network/model call. +- Release diff validates both compared releases through the same fail-closed authoritative-use gate so comparison cannot bypass contract-version, publication-state, or truth-status policy. - Declared digest syntax validation is explicitly separated from future cryptographic byte verification to prevent false integrity claims. - Unsafe Rust is forbidden in the core domain and client crates. diff --git a/docs/PRD.md b/docs/PRD.md index 5e17389d..7f464610 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -58,11 +58,13 @@ All LLM-backed induction uses `contextual-orchestrator`. Model output is untrust A consuming product can inspect a versioned `semantic_release` offline and fail closed before authoritative use. The first Client slice requires stable release identity, contract and ontology versions, truth/publication state, declared SHA-256 digest identity, provenance references, and unique concept identifiers. Admission requires an explicitly supported contract version plus `Published` and `Authoritative` state. Consuming products retain their own tenant/purpose authorization and physical data/query execution. +An admitted client can also compare two releases deterministically without contacting a model/provider. Release diff applies the same authoritative-use admission policy to both inputs before returning stable previous/current release identity and sorted added/removed concept identifiers. Diff is semantic-contract evidence only; it does not authorize downstream data access, calculate business measures, mutate either release, or infer consuming-domain impact automatically. + The current digest value object validates the declared `sha256:<64 hex>` identity shape. Cryptographic integrity is not claimed until a later verifier hashes the exact serialized artifact bytes and compares the result. ## 6. First Generation ↔ Client vertical -`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission -> consuming-product ACL/query boundary`. +`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission/diff -> consuming-product ACL/query boundary`. `ContextualWisdomLab/governance-risk-compliance` is the first reference source/client scenario, not a special-case algorithm. A shared golden fixture must exercise both Generation and Client without copying GRC truth into ConceptWeave or giving ConceptWeave direct GRC application-table access. @@ -89,5 +91,6 @@ The current digest value object validates the declared `sha256:<64 hex>` identit - malformed/hostile source contracts rejected with bounded resource use; - semantic-model release can be reproduced from source receipts and approved proposal receipts; - consumer can validate release schema/version/governance state offline before authoritative use; +- consumer can deterministically diff admitted releases without provider access or bypassing release admission; - exact serialized artifact digest verification exists before integrity is claimed; - buyer can inspect why each published artifact exists and which evidence supported it. From dbca01c73d2c8fe009ea3511c93feda3a29d6ae1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:47:42 +0900 Subject: [PATCH 19/67] test(client): specify serialized release digest verification --- .../tests/release_integrity.rs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 crates/conceptweave-client/tests/release_integrity.rs diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs new file mode 100644 index 00000000..f874145b --- /dev/null +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -0,0 +1,54 @@ +use conceptweave_client::{ + ReleaseContractError, ReleaseDigest, ReleaseMetadata, SemanticRelease, SemanticReleaseClient, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +const ARTIFACT_BYTES: &[u8] = b"conceptweave-semantic-release-v1"; +const ARTIFACT_DIGEST: &str = + "sha256:a141df3d94076487b7063ccb10d62a723f922b4440fa145fa16fd661d7259d1d"; + +fn release_with_digest(digest: &str) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new( + "semantic-release-grc-integrity-v1", + "1.0.0", + "grc-ontology-2026-09", + ) + .unwrap(), + TruthStatus::Authoritative, + PublicationState::Published, + ReleaseDigest::new(digest).unwrap(), + vec![EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_evidence.control_identifier", + ) + .unwrap()], + vec!["control.evidence".to_string()], + ) + .unwrap() +} + +#[test] +fn serialized_artifact_digest_verification_accepts_exact_bytes_offline() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release_with_digest(ARTIFACT_DIGEST); + + assert_eq!(client.verify_serialized_artifact(&release, ARTIFACT_BYTES), Ok(())); +} + +#[test] +fn serialized_artifact_digest_verification_rejects_changed_bytes() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release_with_digest(ARTIFACT_DIGEST); + + let result = client.verify_serialized_artifact( + &release, + b"conceptweave-semantic-release-v1-tampered", + ); + + assert!(matches!( + result, + Err(ReleaseContractError::ArtifactDigestMismatch { .. }) + )); +} From 8d6bb82e57bfed461710cff9d992e93bea3b3626 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:50:20 +0900 Subject: [PATCH 20/67] test(client): format serialized digest RED --- .../tests/release_integrity.rs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs index f874145b..903ef5cd 100644 --- a/crates/conceptweave-client/tests/release_integrity.rs +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -18,12 +18,14 @@ fn release_with_digest(digest: &str) -> SemanticRelease { TruthStatus::Authoritative, PublicationState::Published, ReleaseDigest::new(digest).unwrap(), - vec![EvidenceReference::new( - "snapshot:grc-schema-2026-09-01", - "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "public.control_evidence.control_identifier", - ) - .unwrap()], + vec![ + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_evidence.control_identifier", + ) + .unwrap(), + ], vec!["control.evidence".to_string()], ) .unwrap() @@ -34,7 +36,10 @@ fn serialized_artifact_digest_verification_accepts_exact_bytes_offline() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); let release = release_with_digest(ARTIFACT_DIGEST); - assert_eq!(client.verify_serialized_artifact(&release, ARTIFACT_BYTES), Ok(())); + assert_eq!( + client.verify_serialized_artifact(&release, ARTIFACT_BYTES), + Ok(()) + ); } #[test] @@ -42,10 +47,8 @@ fn serialized_artifact_digest_verification_rejects_changed_bytes() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); let release = release_with_digest(ARTIFACT_DIGEST); - let result = client.verify_serialized_artifact( - &release, - b"conceptweave-semantic-release-v1-tampered", - ); + let result = + client.verify_serialized_artifact(&release, b"conceptweave-semantic-release-v1-tampered"); assert!(matches!( result, From 29d068bfb420e28eb5c7c3efd6924667014192f5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:57:09 +0900 Subject: [PATCH 21/67] feat(client): verify serialized release digest --- .github/workflows/product.yml | 6 ++- crates/conceptweave-client/Cargo.toml | 1 + crates/conceptweave-client/src/lib.rs | 49 +++++++++++++++++-- .../tests/error_messages.rs | 8 +++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index c375203d..9b370b32 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -114,7 +114,11 @@ jobs: run: | cargo generate-lockfile --locked git ls-files --error-unmatch Cargo.lock >/dev/null - test -z "$(git status --porcelain=v1 --untracked-files=all -- Cargo.lock)" + if ! test -z "$(git status --porcelain=v1 --untracked-files=all -- Cargo.lock)"; then + echo "::error::Cargo.lock changed while validating the declared dependency graph" + git diff -- Cargo.lock + exit 1 + fi - name: Clean working tree run: test -z "$(git status --porcelain=v1 --untracked-files=all)" diff --git a/crates/conceptweave-client/Cargo.toml b/crates/conceptweave-client/Cargo.toml index 916fa583..1b71255e 100644 --- a/crates/conceptweave-client/Cargo.toml +++ b/crates/conceptweave-client/Cargo.toml @@ -9,3 +9,4 @@ description = "Offline semantic-release admission contracts for ConceptWeave con [dependencies] conceptweave-domain = { path = "../conceptweave-domain" } +sha2 = "0.10.9" diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index bf20a1ab..de4ff3de 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -9,14 +9,16 @@ use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; use core::fmt; +use core::fmt::Write as _; +use sha2::{Digest, Sha256}; use std::collections::BTreeSet; /// A validated content-digest identity carried by a semantic release. /// /// The current contract accepts only the canonical `sha256:<64 lowercase hex>` -/// shape. This value object validates digest identity syntax; byte-for-byte -/// cryptographic re-hashing belongs to the serialized-artifact verification -/// adapter. +/// shape. This value object validates digest identity syntax; exact serialized +/// bytes are cryptographically verified by +/// [`SemanticReleaseClient::verify_serialized_artifact`]. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ReleaseDigest(String); @@ -268,6 +270,36 @@ impl SemanticReleaseClient { Ok(()) } + /// Verifies the SHA-256 digest of exact serialized semantic-release bytes. + /// + /// The release must first satisfy the same authoritative-use admission gate + /// as other Client operations. The caller supplies the exact bytes whose + /// identity is declared by [`SemanticRelease::artifact_digest`]; this method + /// performs no network access, parsing, provider call, or source-system read. + pub fn verify_serialized_artifact( + &self, + release: &SemanticRelease, + artifact_bytes: &[u8], + ) -> Result<(), ReleaseContractError> { + self.validate_for_authoritative_use(release)?; + + let digest = Sha256::digest(artifact_bytes); + let mut computed = String::with_capacity("sha256:".len() + digest.len() * 2); + computed.push_str("sha256:"); + for byte in digest { + write!(&mut computed, "{byte:02x}").expect("writing to String cannot fail"); + } + + let declared = release.artifact_digest().as_str(); + if computed != declared { + return Err(ReleaseContractError::ArtifactDigestMismatch { + declared: declared.to_string(), + computed, + }); + } + Ok(()) + } + /// Compares two admitted releases and reports deterministic concept changes. /// /// Both releases pass the same authoritative-use admission gate before any @@ -319,6 +351,13 @@ pub enum ReleaseContractError { EmptyField(&'static str), /// The declared release digest is not canonical `sha256:<64 lowercase hex>`. InvalidDigest, + /// Exact serialized bytes do not match the digest declared by the release. + ArtifactDigestMismatch { + /// Digest coordinate declared by the semantic release. + declared: String, + /// SHA-256 digest computed from the exact supplied bytes. + computed: String, + }, /// The release carries no provenance evidence. MissingProvenance, /// The release repeats one semantic concept identity. @@ -350,6 +389,10 @@ impl fmt::Display for ReleaseContractError { formatter, "release digest must use sha256:<64 lowercase hex>" ), + Self::ArtifactDigestMismatch { declared, computed } => write!( + formatter, + "semantic release artifact digest mismatch: declared `{declared}`, computed `{computed}`" + ), Self::MissingProvenance => { write!(formatter, "semantic releases require provenance evidence") } diff --git a/crates/conceptweave-client/tests/error_messages.rs b/crates/conceptweave-client/tests/error_messages.rs index d366cf52..c10762cb 100644 --- a/crates/conceptweave-client/tests/error_messages.rs +++ b/crates/conceptweave-client/tests/error_messages.rs @@ -12,6 +12,14 @@ fn contract_errors_explain_the_failed_admission_invariant() { ReleaseContractError::InvalidDigest, "release digest must use sha256:<64 lowercase hex>".to_string(), ), + ( + ReleaseContractError::ArtifactDigestMismatch { + declared: "sha256:declared".to_string(), + computed: "sha256:computed".to_string(), + }, + "semantic release artifact digest mismatch: declared `sha256:declared`, computed `sha256:computed`" + .to_string(), + ), ( ReleaseContractError::MissingProvenance, "semantic releases require provenance evidence".to_string(), From 8189666930c78adc2ed17cb2a300d533d70ce36f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 02:00:25 +0900 Subject: [PATCH 22/67] fix(client): remove unreachable digest formatting branch --- crates/conceptweave-client/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index de4ff3de..4257c879 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -9,7 +9,6 @@ use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; use core::fmt; -use core::fmt::Write as _; use sha2::{Digest, Sha256}; use std::collections::BTreeSet; @@ -283,11 +282,15 @@ impl SemanticReleaseClient { ) -> Result<(), ReleaseContractError> { self.validate_for_authoritative_use(release)?; + const HEX: &[u8; 16] = b"0123456789abcdef"; let digest = Sha256::digest(artifact_bytes); let mut computed = String::with_capacity("sha256:".len() + digest.len() * 2); computed.push_str("sha256:"); for byte in digest { - write!(&mut computed, "{byte:02x}").expect("writing to String cannot fail"); + let high_nibble = usize::from(byte >> 4); + let low_nibble = usize::from(byte & 0x0f); + computed.push(char::from(HEX[high_nibble])); + computed.push(char::from(HEX[low_nibble])); } let declared = release.artifact_digest().as_str(); From d4fc010b2491a52529b7bfcecbb9c1780838993f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 02:02:27 +0900 Subject: [PATCH 23/67] test(client): cover integrity admission failure --- .../tests/release_integrity.rs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs index 903ef5cd..b04b3362 100644 --- a/crates/conceptweave-client/tests/release_integrity.rs +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -7,7 +7,7 @@ const ARTIFACT_BYTES: &[u8] = b"conceptweave-semantic-release-v1"; const ARTIFACT_DIGEST: &str = "sha256:a141df3d94076487b7063ccb10d62a723f922b4440fa145fa16fd661d7259d1d"; -fn release_with_digest(digest: &str) -> SemanticRelease { +fn release_with_state(digest: &str, publication_state: PublicationState) -> SemanticRelease { SemanticRelease::new( ReleaseMetadata::new( "semantic-release-grc-integrity-v1", @@ -16,7 +16,7 @@ fn release_with_digest(digest: &str) -> SemanticRelease { ) .unwrap(), TruthStatus::Authoritative, - PublicationState::Published, + publication_state, ReleaseDigest::new(digest).unwrap(), vec![ EvidenceReference::new( @@ -31,10 +31,14 @@ fn release_with_digest(digest: &str) -> SemanticRelease { .unwrap() } +fn published_release(digest: &str) -> SemanticRelease { + release_with_state(digest, PublicationState::Published) +} + #[test] fn serialized_artifact_digest_verification_accepts_exact_bytes_offline() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = release_with_digest(ARTIFACT_DIGEST); + let release = published_release(ARTIFACT_DIGEST); assert_eq!( client.verify_serialized_artifact(&release, ARTIFACT_BYTES), @@ -45,7 +49,7 @@ fn serialized_artifact_digest_verification_accepts_exact_bytes_offline() { #[test] fn serialized_artifact_digest_verification_rejects_changed_bytes() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = release_with_digest(ARTIFACT_DIGEST); + let release = published_release(ARTIFACT_DIGEST); let result = client.verify_serialized_artifact(&release, b"conceptweave-semantic-release-v1-tampered"); @@ -55,3 +59,16 @@ fn serialized_artifact_digest_verification_rejects_changed_bytes() { Err(ReleaseContractError::ArtifactDigestMismatch { .. }) )); } + +#[test] +fn serialized_artifact_digest_verification_rejects_unpublished_release() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release_with_state(ARTIFACT_DIGEST, PublicationState::Proposed); + + assert_eq!( + client.verify_serialized_artifact(&release, ARTIFACT_BYTES), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Proposed, + }) + ); +} From ebf7acc9963e841073bbd700f118faade741ed2b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 02:05:16 +0900 Subject: [PATCH 24/67] chore(client): lock digest dependency graph --- CHANGELOG.md | 4 ++- Cargo.lock | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2225cb5c..fb601113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to ConceptWeave are documented here. - Draft 2020-12 JSON Schema for the semantic-candidate public contract. - Rust-first `conceptweave-client` supporting subdomain with deterministic offline semantic-release admission by contract version, publication state, truth status, provenance, stable concept identity, and declared SHA-256 digest identity. - Deterministic offline semantic-release diff that first applies the same authoritative-use admission policy, then reports stable previous/current release identity and sorted added/removed concept identifiers without network or model calls. +- Exact offline SHA-256 verification of caller-supplied serialized semantic-release bytes, with typed digest-mismatch evidence and the same fail-closed authoritative-use admission gate. - Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. - Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. @@ -20,5 +21,6 @@ All notable changes to ConceptWeave are documented here. - Model-generated semantics remain non-authoritative until deterministic validation and authorized review. - Client authoritative-use admission rejects incompatible, unpublished, or non-authoritative releases without requiring a network/model call. - Release diff validates both compared releases through the same fail-closed authoritative-use gate so comparison cannot bypass contract-version, publication-state, or truth-status policy. -- Declared digest syntax validation is explicitly separated from future cryptographic byte verification to prevent false integrity claims. +- Serialized-artifact integrity verification first applies authoritative-use admission, then computes SHA-256 over the exact supplied bytes and rejects any mismatch with the declared release digest. +- Digest syntax validation remains distinct from byte verification so a syntactically valid digest is never treated as proof that serialized content matches it. - Unsafe Rust is forbidden in the core domain and client crates. diff --git a/Cargo.lock b/Cargo.lock index 5755236a..35e09dda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,97 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "conceptweave-client" version = "0.1.0" dependencies = [ "conceptweave-domain", + "sha2", ] [[package]] name = "conceptweave-domain" version = "0.1.0" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" From de083fba1a257ed66935c9ff52963c8f397e7783 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 03:45:35 +0900 Subject: [PATCH 25/67] test(client): specify exact concept resolution --- .../tests/concept_resolution.rs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 crates/conceptweave-client/tests/concept_resolution.rs diff --git a/crates/conceptweave-client/tests/concept_resolution.rs b/crates/conceptweave-client/tests/concept_resolution.rs new file mode 100644 index 00000000..cbbcb900 --- /dev/null +++ b/crates/conceptweave-client/tests/concept_resolution.rs @@ -0,0 +1,73 @@ +use conceptweave_client::{ + ReleaseContractError, ReleaseDigest, ReleaseMetadata, SemanticRelease, SemanticReleaseClient, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_item.control_identifier", + ) + .unwrap() +} + +fn release(publication_state: PublicationState) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new( + "semantic-release-grc-2026-09-01", + "1.0.0", + "grc-ontology-2026-09", + ) + .unwrap(), + TruthStatus::Authoritative, + publication_state, + ReleaseDigest::new( + "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + ) + .unwrap(), + vec![evidence()], + vec![ + "control.internal_control".to_string(), + "evidence.control_evidence".to_string(), + ], + ) + .unwrap() +} + +#[test] +fn exact_concept_resolution_is_deterministic_and_does_not_fuzzy_match() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release(PublicationState::Published); + + assert_eq!( + client.resolve_concept(&release, "control.internal_control"), + Ok(Some("control.internal_control")) + ); + assert_eq!(client.resolve_concept(&release, "internal control"), Ok(None)); + assert_eq!(client.resolve_concept(&release, "CONTROL.INTERNAL_CONTROL"), Ok(None)); +} + +#[test] +fn concept_resolution_reuses_authoritative_release_admission() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let reviewed = release(PublicationState::Reviewed); + + assert_eq!( + client.resolve_concept(&reviewed, "control.internal_control"), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }) + ); +} + +#[test] +fn concept_resolution_rejects_blank_identifiers() { + let client = SemanticReleaseClient::new("1.0.0").unwrap(); + let release = release(PublicationState::Published); + + assert_eq!( + client.resolve_concept(&release, " "), + Err(ReleaseContractError::EmptyField("concept_id")) + ); +} From 827080d101b3d057b4626d845f51d7d575f773f1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 04:48:48 +0900 Subject: [PATCH 26/67] test(client): format concept resolution RED --- crates/conceptweave-client/tests/concept_resolution.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/conceptweave-client/tests/concept_resolution.rs b/crates/conceptweave-client/tests/concept_resolution.rs index cbbcb900..be5cb825 100644 --- a/crates/conceptweave-client/tests/concept_resolution.rs +++ b/crates/conceptweave-client/tests/concept_resolution.rs @@ -44,8 +44,14 @@ fn exact_concept_resolution_is_deterministic_and_does_not_fuzzy_match() { client.resolve_concept(&release, "control.internal_control"), Ok(Some("control.internal_control")) ); - assert_eq!(client.resolve_concept(&release, "internal control"), Ok(None)); - assert_eq!(client.resolve_concept(&release, "CONTROL.INTERNAL_CONTROL"), Ok(None)); + assert_eq!( + client.resolve_concept(&release, "internal control"), + Ok(None) + ); + assert_eq!( + client.resolve_concept(&release, "CONTROL.INTERNAL_CONTROL"), + Ok(None) + ); } #[test] From 4b4c47f363f46ad6d2923ea076e12b34cbf15eaf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 05:58:18 +0900 Subject: [PATCH 27/67] feat(client): resolve exact admitted concept identifiers --- crates/conceptweave-client/src/lib.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 4257c879..06476356 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -269,6 +269,25 @@ impl SemanticReleaseClient { Ok(()) } + /// Resolves one exact concept identifier from an admitted semantic release. + /// + /// Resolution is deliberately exact and deterministic: it performs no + /// case-folding, fuzzy matching, ontology inference, provider call, or + /// mutation. The release must first pass authoritative-use admission. + pub fn resolve_concept<'release>( + &self, + release: &'release SemanticRelease, + concept_id: &str, + ) -> Result, ReleaseContractError> { + require_non_blank(concept_id, "concept_id")?; + self.validate_for_authoritative_use(release)?; + Ok(release + .concept_ids() + .iter() + .map(String::as_str) + .find(|candidate| *candidate == concept_id)) + } + /// Verifies the SHA-256 digest of exact serialized semantic-release bytes. /// /// The release must first satisfy the same authoritative-use admission gate From 5713b99750673df1b3239253997effa8be5c5142 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 06:47:25 +0900 Subject: [PATCH 28/67] test(client): define detached artifact digest contract --- .../tests/release_integrity.rs | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs index b04b3362..0e5f2cb8 100644 --- a/crates/conceptweave-client/tests/release_integrity.rs +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -3,9 +3,9 @@ use conceptweave_client::{ }; use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; -const ARTIFACT_BYTES: &[u8] = b"conceptweave-semantic-release-v1"; -const ARTIFACT_DIGEST: &str = - "sha256:a141df3d94076487b7063ccb10d62a723f922b4440fa145fa16fd661d7259d1d"; +const DETACHED_ARTIFACT_BYTES: &[u8] = b"conceptweave-semantic-model-artifact-v1"; +const DETACHED_ARTIFACT_DIGEST: &str = + "sha256:f7e5724361404225839436726782e8c8bcfe66cfc1b7e844df6c8b93d616244a"; fn release_with_state(digest: &str, publication_state: PublicationState) -> SemanticRelease { SemanticRelease::new( @@ -36,23 +36,25 @@ fn published_release(digest: &str) -> SemanticRelease { } #[test] -fn serialized_artifact_digest_verification_accepts_exact_bytes_offline() { +fn detached_artifact_digest_verification_accepts_exact_bytes_offline() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = published_release(ARTIFACT_DIGEST); + let release = published_release(DETACHED_ARTIFACT_DIGEST); assert_eq!( - client.verify_serialized_artifact(&release, ARTIFACT_BYTES), + client.verify_detached_artifact(&release, DETACHED_ARTIFACT_BYTES), Ok(()) ); } #[test] -fn serialized_artifact_digest_verification_rejects_changed_bytes() { +fn detached_artifact_digest_verification_rejects_changed_bytes() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = published_release(ARTIFACT_DIGEST); + let release = published_release(DETACHED_ARTIFACT_DIGEST); - let result = - client.verify_serialized_artifact(&release, b"conceptweave-semantic-release-v1-tampered"); + let result = client.verify_detached_artifact( + &release, + b"conceptweave-semantic-model-artifact-v1-tampered", + ); assert!(matches!( result, @@ -61,12 +63,15 @@ fn serialized_artifact_digest_verification_rejects_changed_bytes() { } #[test] -fn serialized_artifact_digest_verification_rejects_unpublished_release() { +fn detached_artifact_digest_verification_rejects_unpublished_release() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = release_with_state(ARTIFACT_DIGEST, PublicationState::Proposed); + let release = release_with_state( + DETACHED_ARTIFACT_DIGEST, + PublicationState::Proposed, + ); assert_eq!( - client.verify_serialized_artifact(&release, ARTIFACT_BYTES), + client.verify_detached_artifact(&release, DETACHED_ARTIFACT_BYTES), Err(ReleaseContractError::ReleaseNotPublished { actual: PublicationState::Proposed, }) From ed22957471f7c62b644f68e4f37bdb86327d8668 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 06:47:52 +0900 Subject: [PATCH 29/67] test(client): correct detached artifact digest fixture --- crates/conceptweave-client/tests/release_integrity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs index 0e5f2cb8..49ef937c 100644 --- a/crates/conceptweave-client/tests/release_integrity.rs +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -5,7 +5,7 @@ use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; const DETACHED_ARTIFACT_BYTES: &[u8] = b"conceptweave-semantic-model-artifact-v1"; const DETACHED_ARTIFACT_DIGEST: &str = - "sha256:f7e5724361404225839436726782e8c8bcfe66cfc1b7e844df6c8b93d616244a"; + "sha256:13b5f6c3d51da7bd481e8d267a135f0c7ef2a7a4e3987ceb6a1b610e215ccefd"; fn release_with_state(digest: &str, publication_state: PublicationState) -> SemanticRelease { SemanticRelease::new( From 398d8d6878706251397267d8fd8a660d4c2ecc7e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 11:43:37 +0900 Subject: [PATCH 30/67] style(client): keep detached artifact RED rustfmt-clean --- crates/conceptweave-client/tests/release_integrity.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/conceptweave-client/tests/release_integrity.rs b/crates/conceptweave-client/tests/release_integrity.rs index 49ef937c..c70d8b5f 100644 --- a/crates/conceptweave-client/tests/release_integrity.rs +++ b/crates/conceptweave-client/tests/release_integrity.rs @@ -65,10 +65,7 @@ fn detached_artifact_digest_verification_rejects_changed_bytes() { #[test] fn detached_artifact_digest_verification_rejects_unpublished_release() { let client = SemanticReleaseClient::new("1.0.0").unwrap(); - let release = release_with_state( - DETACHED_ARTIFACT_DIGEST, - PublicationState::Proposed, - ); + let release = release_with_state(DETACHED_ARTIFACT_DIGEST, PublicationState::Proposed); assert_eq!( client.verify_detached_artifact(&release, DETACHED_ARTIFACT_BYTES), From 091c36b24330671952de378d3596afcde5f62351 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 16:44:03 +0900 Subject: [PATCH 31/67] test(client): specify explicit legacy compatibility policy --- .../tests/release_compatibility.rs | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 crates/conceptweave-client/tests/release_compatibility.rs diff --git a/crates/conceptweave-client/tests/release_compatibility.rs b/crates/conceptweave-client/tests/release_compatibility.rs new file mode 100644 index 00000000..824af8ec --- /dev/null +++ b/crates/conceptweave-client/tests/release_compatibility.rs @@ -0,0 +1,107 @@ +use conceptweave_client::{ + ContractVersionCompatibility, ReleaseContractError, ReleaseDigest, ReleaseMetadata, + SemanticRelease, SemanticReleaseClient, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "public.control_evidence.control_identifier", + ) + .expect("evidence fixture is valid") +} + +fn release(contract_version: &str) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new( + format!("semantic_release_{contract_version}"), + contract_version, + "grc_ontology_2026_09", + ) + .expect("metadata fixture is valid"), + TruthStatus::Authoritative, + PublicationState::Published, + ReleaseDigest::new( + "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + ) + .expect("digest fixture is valid"), + vec![evidence()], + vec!["control.evidence".to_owned()], + ) + .expect("release fixture is valid") +} + +#[test] +fn client_explicitly_distinguishes_current_supported_legacy_and_unknown_versions() { + let client = SemanticReleaseClient::with_supported_legacy_contract_versions( + "2.0.0", + vec!["1.1.0".to_owned(), "1.0.0".to_owned()], + ) + .expect("explicit compatibility policy is valid"); + + assert_eq!( + client.compatibility(&release("2.0.0")), + ContractVersionCompatibility::Current + ); + assert_eq!( + client.compatibility(&release("1.0.0")), + ContractVersionCompatibility::SupportedLegacy + ); + assert_eq!( + client.compatibility(&release("3.0.0")), + ContractVersionCompatibility::Unsupported + ); +} + +#[test] +fn supported_legacy_release_passes_the_same_authoritative_use_gate() { + let client = SemanticReleaseClient::with_supported_legacy_contract_versions( + "2.0.0", + vec!["1.0.0".to_owned()], + ) + .expect("explicit compatibility policy is valid"); + + assert_eq!(client.validate_for_authoritative_use(&release("1.0.0")), Ok(())); +} + +#[test] +fn unknown_version_still_fails_closed_when_legacy_support_exists() { + let client = SemanticReleaseClient::with_supported_legacy_contract_versions( + "2.0.0", + vec!["1.0.0".to_owned()], + ) + .expect("explicit compatibility policy is valid"); + + assert_eq!( + client.validate_for_authoritative_use(&release("0.9.0")), + Err(ReleaseContractError::UnsupportedContractVersion { + expected: "2.0.0".to_owned(), + actual: "0.9.0".to_owned(), + }) + ); +} + +#[test] +fn compatibility_policy_rejects_blank_or_current_version_as_legacy() { + assert_eq!( + SemanticReleaseClient::with_supported_legacy_contract_versions( + "2.0.0", + vec![" ".to_owned()] + ), + Err(ReleaseContractError::EmptyField( + "supported_legacy_contract_version" + )) + ); + + assert_eq!( + SemanticReleaseClient::with_supported_legacy_contract_versions( + "2.0.0", + vec!["2.0.0".to_owned()] + ), + Err(ReleaseContractError::CurrentContractVersionMarkedLegacy( + "2.0.0".to_owned() + )) + ); +} From 2a4596e88d016e01a3bffded7a8436b14d55ec18 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 16:58:15 +0900 Subject: [PATCH 32/67] feat(client): implement explicit legacy compatibility --- crates/conceptweave-client/src/lib.rs | 83 ++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 06476356..a7213199 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -218,30 +218,93 @@ impl SemanticReleaseDiff { } } -/// Offline admission policy for one supported semantic-release contract version. +/// Compatibility classification for one semantic-release contract version. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ContractVersionCompatibility { + /// The release uses the client's current contract version. + Current, + /// The release uses a legacy version explicitly admitted by client policy. + SupportedLegacy, + /// The release version is neither current nor explicitly supported legacy. + Unsupported, +} + +/// Offline admission policy for current and explicitly supported legacy contract versions. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SemanticReleaseClient { supported_contract_version: String, + supported_legacy_contract_versions: BTreeSet, } impl SemanticReleaseClient { - /// Creates a client pinned to one explicit semantic-release contract version. + /// Creates a client pinned to one explicit current semantic-release contract version. pub fn new( supported_contract_version: impl Into, + ) -> Result { + Self::with_supported_legacy_contract_versions(supported_contract_version, Vec::new()) + } + + /// Creates a client with an explicit current version and explicit supported legacy versions. + /// + /// Legacy support is opt-in rather than inferred from version ordering. Blank versions and the + /// current version repeated as legacy are rejected so admission policy remains unambiguous. + pub fn with_supported_legacy_contract_versions( + supported_contract_version: impl Into, + supported_legacy_contract_versions: Vec, ) -> Result { let supported_contract_version = supported_contract_version.into(); require_non_blank(&supported_contract_version, "supported_contract_version")?; + + let mut validated_legacy_versions = BTreeSet::new(); + for legacy_version in supported_legacy_contract_versions { + require_non_blank( + &legacy_version, + "supported_legacy_contract_version", + )?; + if legacy_version == supported_contract_version { + return Err(ReleaseContractError::CurrentContractVersionMarkedLegacy( + legacy_version, + )); + } + validated_legacy_versions.insert(legacy_version); + } + Ok(Self { supported_contract_version, + supported_legacy_contract_versions: validated_legacy_versions, }) } - /// Returns the exact semantic-release contract version this client accepts. + /// Returns the exact current semantic-release contract version this client accepts. pub fn supported_contract_version(&self) -> &str { &self.supported_contract_version } - /// Fails closed unless a release is compatible, Published and Authoritative. + /// Returns explicitly supported legacy contract versions in deterministic order. + pub fn supported_legacy_contract_versions(&self) -> impl Iterator { + self.supported_legacy_contract_versions + .iter() + .map(String::as_str) + } + + /// Classifies a release against the client's explicit compatibility policy. + /// + /// Version ordering is deliberately not inferred. A version is compatible only when it equals + /// the current version or appears in the explicit legacy allow-set. + pub fn compatibility(&self, release: &SemanticRelease) -> ContractVersionCompatibility { + if release.contract_version() == self.supported_contract_version { + ContractVersionCompatibility::Current + } else if self + .supported_legacy_contract_versions + .contains(release.contract_version()) + { + ContractVersionCompatibility::SupportedLegacy + } else { + ContractVersionCompatibility::Unsupported + } + } + + /// Fails closed unless a release is explicitly compatible, Published and Authoritative. /// /// This check is deterministic and performs no network or model calls. It is /// suitable as an admission gate before a consuming product performs its own @@ -250,7 +313,7 @@ impl SemanticReleaseClient { &self, release: &SemanticRelease, ) -> Result<(), ReleaseContractError> { - if release.contract_version() != self.supported_contract_version { + if self.compatibility(release) == ContractVersionCompatibility::Unsupported { return Err(ReleaseContractError::UnsupportedContractVersion { expected: self.supported_contract_version.clone(), actual: release.contract_version().to_string(), @@ -384,9 +447,11 @@ pub enum ReleaseContractError { MissingProvenance, /// The release repeats one semantic concept identity. DuplicateConceptId(String), + /// The configured current contract version was also supplied as a legacy version. + CurrentContractVersionMarkedLegacy(String), /// The release uses a contract version this client does not support. UnsupportedContractVersion { - /// Contract version required by the client. + /// Current contract version required by the client when no explicit compatibility exists. expected: String, /// Contract version supplied by the release. actual: String, @@ -422,9 +487,13 @@ impl fmt::Display for ReleaseContractError { formatter, "semantic release contains duplicate concept id `{concept_id}`" ), + Self::CurrentContractVersionMarkedLegacy(contract_version) => write!( + formatter, + "current semantic release contract version `{contract_version}` cannot also be marked legacy" + ), Self::UnsupportedContractVersion { expected, actual } => write!( formatter, - "semantic release contract version `{actual}` is unsupported; expected `{expected}`" + "semantic release contract version `{actual}` is unsupported; current version is `{expected}`" ), Self::ReleaseNotPublished { actual } => { write!(formatter, "semantic release is {actual:?}, not Published") From 457d05fb021b7d54c93067e00950d550463225c5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 16:58:56 +0900 Subject: [PATCH 33/67] docs(client): record explicit legacy compatibility --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb601113..575e56f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to ConceptWeave are documented here. - Rust-first `conceptweave-client` supporting subdomain with deterministic offline semantic-release admission by contract version, publication state, truth status, provenance, stable concept identity, and declared SHA-256 digest identity. - Deterministic offline semantic-release diff that first applies the same authoritative-use admission policy, then reports stable previous/current release identity and sorted added/removed concept identifiers without network or model calls. - Exact offline SHA-256 verification of caller-supplied serialized semantic-release bytes, with typed digest-mismatch evidence and the same fail-closed authoritative-use admission gate. +- Explicit semantic-release compatibility policy that distinguishes the current contract version, caller-declared supported legacy versions, and unknown versions without inferring compatibility from version ordering; supported legacy releases still pass the same Published/Authoritative gate. - Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. - Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. @@ -20,6 +21,7 @@ All notable changes to ConceptWeave are documented here. - Model-generated semantics remain non-authoritative until deterministic validation and authorized review. - Client authoritative-use admission rejects incompatible, unpublished, or non-authoritative releases without requiring a network/model call. +- Legacy compatibility is explicit opt-in policy; unknown versions remain fail-closed and the current version cannot also be configured as legacy. - Release diff validates both compared releases through the same fail-closed authoritative-use gate so comparison cannot bypass contract-version, publication-state, or truth-status policy. - Serialized-artifact integrity verification first applies authoritative-use admission, then computes SHA-256 over the exact supplied bytes and rejects any mismatch with the declared release digest. - Digest syntax validation remains distinct from byte verification so a syntactically valid digest is never treated as proof that serialized content matches it. From b893648eed60949702d1f6ce94514f5cd7456f3d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 16:59:26 +0900 Subject: [PATCH 34/67] docs(client): align compatibility domain policy --- ARCHITECTURE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4ac642a5..0ae65f42 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -47,11 +47,11 @@ Planned Governance & Publication aggregate for immutable publication. The curren ### ReleaseDigest -Client value object for a declared `sha256:<64 hex>` digest identity. It validates digest syntax only. A later serialized-artifact verifier must hash the exact bytes and compare the result before integrity is claimed. +Client value object for a declared `sha256:<64 hex>` digest identity. It validates digest syntax only. Exact detached artifact bytes must be hashed and compared before integrity is claimed. ### SemanticReleaseClient -A stateless domain service in Client Consumption that admits a release for authoritative use only when the contract version is supported and the release is both `Published` and `Authoritative`. It performs no network, LLM, database, tenant-authorization, or physical-query work. +A stateless domain service in Client Consumption. Its compatibility policy has one explicit current contract version and an explicit set of supported legacy versions; it never infers compatibility from semantic-version ordering. Unknown versions fail closed. Current and supported-legacy releases pass the same `Published` plus `Authoritative` gate before resolution, diff, or artifact verification. It performs no network, LLM, database, tenant-authorization, or physical-query work. ## Truth model From 7fe7dc0262949fbd48d7c8f0f92e948db2888b24 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:00:16 +0900 Subject: [PATCH 35/67] docs(gap): reconcile client compatibility progress --- docs/product-technical-gap-baseline.md | 73 ++++++++++++++------------ 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 6a597d35..6b031b25 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -11,56 +11,61 @@ Only the repository bootstrap README exists before the foundation PR. No product | Area | Owner | Status | Evidence / action / next verification | | --- | --- | --- | --- | | Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against the exact PR #1 head before merge. | -| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated while the public transition API fails closed at steward-reviewed/publication boundaries; Draft 2020-12 candidate schema enforces public candidate shape and Published -> Authoritative consistency. | +| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated while public transition APIs fail closed at steward-reviewed/publication boundaries; Draft 2020-12 candidate schema enforces public candidate shape and Published -> Authoritative consistency. | | Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | -| Quality gate | ConceptWeave | ACTIVE_PR | Product workflow checks exact checkout, CI contract, fmt, Clippy, tests, rustdoc, exact owned 100% line/function/region/source-branch coverage, JSON contracts, lock freshness, and clean tree. Foundation PR #1 current exact head must supply fresh evidence; predecessor evidence never transfers. | -| Standards/research | ConceptWeave | ACTIVE_PR | Stable-vs-draft standards plus paper-by-paper Generation/Client/Bridge/cross-cutting capability and evaluation traceability. | -| Security/test/operability | ConceptWeave + central `.github` security workflow | ACTIVE_PR / CONTROL_PLANE_BLOCKED | Product and SAST execute on the exact foundation head. Security Scan is fail-closed because Dependency Review authoritative comparison evidence is currently unavailable; sibling scanners do not substitute. | +| Quality gate | ConceptWeave | ACTIVE_PR | Exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` has Product run `33527150325` and SAST run `33527150417` terminal success. | +| Security/test/operability | ConceptWeave + central `.github` | CONTROL_PLANE_BLOCKED | Security Scan run `33527150445` reached exact checkout; dependency-review job `100059571813` failed at `Check dependency review support`, so the pinned Dependency Review step was skipped. OSV/Trivy/Scorecard succeeded but are not substitutes. | +| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; no self-approval or routine admin bypass is accepted. | ## Active Client Consumption slice — PR #5 / Issue #3 -PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. The canonical exact head is the live GitHub PR head; it is not duplicated as a self-referential constant in this file because editing this baseline itself changes that SHA. Check results are valid only for the unchanged live PR head. +PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. The canonical exact head is the live GitHub PR head; editing this file changes that SHA, so check evidence is valid only for the later unchanged branch head. | Gap | Owner | Status | Evidence | Action | Next verification | | --- | --- | --- | --- | --- | --- | -| Offline release admission | Client Consumption | IMPLEMENTED_ACTIVE_PR | Test-first commits define and implement `SemanticReleaseClient`; authoritative use requires exact supported contract version + Published + Authoritative. | Keep deterministic and provider-independent. | Exact-head Rust tests/Clippy/docs/coverage. | -| Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_ACTIVE_PR | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance, unique concept IDs. | Stabilize compatibility/deprecation semantics before generated language bindings. | Exact-head AJV + Rust contract parity. | -| Declared digest identity | Client Consumption | PARTIAL | `ReleaseDigest` accepts only `sha256:<64 hex>`. | Add exact serialized-byte hashing and digest comparison before integrity is claimed; later add signature/provenance verification where release design warrants it. | Golden artifact mutation/tamper fixtures. | -| Release compatibility | Client Consumption | PARTIAL | Exact-version admission exists. | Add supported-version range/deprecation policy, malformed/unknown/older-supported/superseded cases. | Compatibility matrix fixtures. | -| Release diff / stale handling | Client Consumption | GAP | Research traceability maps OM4OV to explicit version-change semantics. | Implement typed `diff` and supersession/staleness outcomes without treating ordinary ontology matching as versioning. | Added/removed/changed entity golden fixtures. | -| Match / resolve / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research register defines retrieve/filter/match constraints. | Implement deterministic candidate retrieval first; optional LLM work only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | -| Query-plan contract | Client Consumption | GAP | Issue #3 requires plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | -| Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave client performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution in consuming products. | Cross-tenant/purpose denial tests in each consumer. | +| Offline release admission | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `SemanticReleaseClient` requires explicit compatibility plus Published + Authoritative and remains provider/network independent. | Preserve downstream tenant/purpose authorization and physical execution boundaries. | Exact-head Rust tests/Clippy/docs/coverage. | +| Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance and unique concept IDs. | Keep language-neutral contract stable before generated bindings. | Exact-head AJV + Rust contract parity. | +| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first byte-verification lineage culminates in `verify_serialized_artifact`, which hashes exact caller-supplied bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. | Add signature/provenance verification only when the publication design defines a stable signing contract. | Exact-head tamper/mutation fixtures and Product run. | +| Release diff | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Deterministic `diff` admits both releases through the same governance/compatibility gate and reports sorted added/removed concept IDs. | Extend only when typed relation/mapping/measure diff contracts exist. | Golden added/removed fixtures and exact-head Product run. | +| Exact concept resolution | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `resolve_concept` performs exact deterministic lookup after authoritative-use admission; no fuzzy/LLM inference. | Add relation and physical-mapping resolution next. | Exact-head edge cases for unknown/blank IDs. | +| Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first commit `091c36b24330671952de378d3596afcde5f62351` specifies Current / SupportedLegacy / Unsupported behavior, same authoritative gate for supported legacy releases, and fail-closed invalid policy. Production commit `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements `ContractVersionCompatibility` plus explicit current/legacy policy without inferring version ordering. | Add explicit deprecation/supersession semantics; do not treat arbitrary older versions as supported. | Hosted exact-head Product/Clippy/tests on the final unchanged documentation head. | +| Match / align / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research traceability defines retrieve/filter/match constraints. | Deterministic candidate retrieval first; optional LLM only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | +| Query-plan contract | Client Consumption | GAP | Issue #3 requires semantic plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | +| Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution downstream. | Cross-tenant/purpose denial tests in each consumer. | -## Central control-plane evidence +## Parallel Source Observation slice — PR #6 / Issue #2 + +PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Live repository evidence on 2026-09-02 shows it now preserves immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, and explicit PostgreSQL 18 FK validation/enforcement state. Its current exact head and checks must be read from PR #6 before integration; sibling predecessor evidence does not transfer into this branch. The next Generation gap remains a bounded read-only PostgreSQL adapter with cancellation/timeout/resource limits and a frozen anonymized GRC fixture. -The runner-admission defect was repaired at the owning central boundary: `ContextualWisdomLab/.github` PR #1618 merged after changing the affected organization-required Security Scan/SAST runner selectors from the observed-starved floating `ubuntu-latest` to explicit `ubuntu-24.04` while retaining exact-head validation, scanner logic, permissions, thresholds and immutable action pins. +## Central control-plane evidence -Fresh foundation PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` proves the runner repair reached this repository: Product run `33527150325` and SAST run `33527150417` are terminal success, and Security Scan run `33527150445` acquired an Ubuntu 24.04 runner and checked out the exact head. Security then failed at a different central evidence boundary: dependency-review job `99920784712` received HTTP `403` with curl exit `0` from the exact dependency-graph comparison `main@f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425...bba351b77bf5f1ab5cfd55979fbb2bd158f78b81`. The fail-closed workflow correctly did not run the pinned Dependency Review action. Central `.github#810` owns this availability/configuration incident; ConceptWeave must not weaken the gate or substitute OSV/Trivy/Scorecard. GREEN requires an unchanged public non-fork head where the exact comparison returns HTTP 200 and the pinned Dependency Review action actually executes terminally. +- `ContextualWisdomLab/.github#712` owns hosted-runner acquisition/queue health; queued jobs before checkout remain incomplete evidence. +- `ContextualWisdomLab/.github#810` owns authoritative Dependency Review availability/configuration. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. +- `ContextualWisdomLab/.github#772` owns the solo-maintainer approval-governance defect. Live ruleset `18156473` still requires one approving review while `required_reviewers=[]`; self-approval/model-as-human/routine bypass are prohibited. +- `ContextualWisdomLab/.github#1219` owns stacked-PR central-review throughput. Leaf repositories must not duplicate the review scheduler. ## Remaining P0 product gaps -1. **Source Observation vertical** — relational schema snapshot contract, real PostgreSQL introspection adapter, immutable digest/location receipts, hostile-input bounds. -2. **Ontology induction** — deterministic observations plus contextual-orchestrator structured candidate generation for concepts, taxonomy, and non-taxonomic relations. -3. **Semantic-layer induction** — dimensions, measures, grain, units, relationships, and physical mappings with deterministic calculation contracts. -4. **Validation engine** — RDF/OWL/SKOS/SHACL publication validation, consistency checks, duplicate/conflict detection, bounded reasoning. -5. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, releases, transactional outbox, bitemporal history where applicable. -6. **Review workflow** — Keyverse tenant/role/purpose context, steward review, maker-checker where required, stale decision protection, immutable publication receipt. -7. **Publication adapters** — OWL/RDFS/SKOS/SHACL/JSON-LD and version-bound Apache Ossie semantic-model export. -8. **Client completion** — byte-level integrity verification, compatibility/deprecation, diff/stale handling, match/resolve/explain/query-plan, generated bindings only when contract stability warrants them. -9. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC, and EA through published contracts only. -10. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility, multilingual cases. -11. **Secure external research** — SearXNG discovery and safe source fetch through the correct CWL egress boundary for ontology grounding, never search snippets as truth. -12. **Observability** — shared CWL OpenTelemetry import/bootstrap contract, detailed structured logs, SIEM security-event projection where applicable. -13. **Release** — SBOM, provenance, signed artifacts, migration/backup/restore evidence, versioned changelog, protected release pipeline. +1. **Source Observation adapter** — real bounded PostgreSQL introspection, immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen GRC fixture. +2. **Observation-to-candidate provenance** — exact source receipt plus discovery method/proposal receipt for every generated candidate. +3. **Ontology induction** — deterministic observations plus `contextual-orchestrator` structured candidate generation for concepts, taxonomy and non-taxonomic relations. +4. **Semantic-layer induction** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts. +5. **Validation engine** — RDF/OWL/SKOS/SHACL publication validation, consistency checks, duplicate/conflict detection and bounded reasoning. +6. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, immutable releases, transactional outbox and temporal history where warranted. +7. **Review workflow** — Keyverse tenant/role/purpose context, steward review, maker-checker where required, stale-decision protection and immutable publication receipt. +8. **Publication adapters** — OWL/RDFS/SKOS/SHACL/JSON-LD and version-bound Apache Ossie export. +9. **Client completion** — deprecation/supersession semantics, relation/mapping/dimension/measure resolution, signature/provenance contract, research-backed match/align/explain, and semantic query-plan API. +10. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC and EA through published contracts only. +11. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility and multilingual cases. +12. **Observability/release** — shared OpenTelemetry bootstrap, structured security events, SBOM/provenance/signing, backup/restore and protected release evidence. ## DDD fitness gaps and invariants - No generic `utils/helpers/services/common` domain buckets are permitted. -- Adapters must remain outside `conceptweave-domain`. -- Client Consumption may consume versioned public contracts but not generator-private implementation. +- Adapters remain outside owned domain/client/source-observation contracts. +- Client Consumption consumes versioned public release contracts only, never generator-private implementation or persistence. +- Source Observation preserves source evidence but does not infer semantic authority. - Foreign product DTOs require Anti-Corruption Layers. -- `semantic-data-portal` must not become ConceptWeave persistence, and ConceptWeave must not become an SDP clone. +- `semantic-data-portal` remains catalog/governance/consumption plane, not ConceptWeave persistence. - Consuming-product authorization/query execution stays downstream; ConceptWeave does not own foreign application tables. -- External forks/tools can be optional adapters but are not CWL-owned product authorities. -- Future persistence uses descriptive two-or-more-word `snake_case` objects, 3NF by default, explicit item-level UPSERT/idempotency contracts, and immutable published releases. +- Future persistence uses descriptive two-or-more-word `snake_case` objects, 3NF by default, explicit item-level UPSERT/idempotency and immutable published releases. From 9df087a5d8f6e46c7e2e91e9c447ee504d00c677 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:00:57 +0900 Subject: [PATCH 36/67] docs(product): define explicit client compatibility --- docs/PRD.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 7f464610..6a30dc4a 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -32,7 +32,7 @@ Produce candidates for concepts, taxonomies, non-taxonomic relations, semantic c ### FR-3 Evidence and provenance -The current v0.1 candidate contract requires every candidate to retain exact source identity, source digest, and source location through `EvidenceReference`. Issue #2 must add immutable Source Observation and proposal-receipt contracts that also retain observation time, parser/extractor revision, and discovery method before the first Generation release. Until those receipt contracts exist, the Rust `SemanticCandidate` and `contracts/semantic-candidate.schema.json` must not be described as already carrying those deferred coordinates. Unsupported candidates fail closed. +The current v0.1 candidate contract requires every candidate to retain exact source identity, source digest, and source location through `EvidenceReference`. Issue #2 must add immutable Source Observation and proposal-receipt contracts that also retain observation time, parser/extractor revision, and discovery method before the first Generation release. Until those receipt contracts exist on an integrated Generation head, the Rust `SemanticCandidate` and `contracts/semantic-candidate.schema.json` must not be described as already carrying those deferred coordinates. Unsupported candidates fail closed. ### FR-4 Deterministic validation @@ -56,15 +56,15 @@ All LLM-backed induction uses `contextual-orchestrator`. Model output is untrust ### FR-9 Client consumption -A consuming product can inspect a versioned `semantic_release` offline and fail closed before authoritative use. The first Client slice requires stable release identity, contract and ontology versions, truth/publication state, declared SHA-256 digest identity, provenance references, and unique concept identifiers. Admission requires an explicitly supported contract version plus `Published` and `Authoritative` state. Consuming products retain their own tenant/purpose authorization and physical data/query execution. +A consuming product can inspect a versioned `semantic_release` offline and fail closed before authoritative use. The first Client slice requires stable release identity, contract and ontology versions, truth/publication state, declared SHA-256 digest identity, provenance references, and unique concept identifiers. Admission accepts only the explicit current contract version or an explicitly configured supported-legacy version, plus `Published` and `Authoritative` state. Compatibility is never inferred from version ordering; unknown versions remain unsupported. Consuming products retain their own tenant/purpose authorization and physical data/query execution. -An admitted client can also compare two releases deterministically without contacting a model/provider. Release diff applies the same authoritative-use admission policy to both inputs before returning stable previous/current release identity and sorted added/removed concept identifiers. Diff is semantic-contract evidence only; it does not authorize downstream data access, calculate business measures, mutate either release, or infer consuming-domain impact automatically. +An admitted client can compare two releases deterministically without contacting a model/provider. Release diff applies the same authoritative-use admission policy to both inputs before returning stable previous/current release identity and sorted added/removed concept identifiers. Diff is semantic-contract evidence only; it does not authorize downstream data access, calculate business measures, mutate either release, or infer consuming-domain impact automatically. -The current digest value object validates the declared `sha256:<64 hex>` identity shape. Cryptographic integrity is not claimed until a later verifier hashes the exact serialized artifact bytes and compares the result. +The digest value object validates canonical `sha256:<64 lowercase hex>` identity syntax. Cryptographic integrity is a separate operation: `SemanticReleaseClient::verify_serialized_artifact` first applies authoritative-use admission, then hashes the exact caller-supplied detached artifact bytes and requires an exact digest match. Syntax validity alone is never integrity evidence. ## 6. First Generation ↔ Client vertical -`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission/diff -> consuming-product ACL/query boundary`. +`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission/diff/integrity verification -> consuming-product ACL/query boundary`. `ContextualWisdomLab/governance-risk-compliance` is the first reference source/client scenario, not a special-case algorithm. A shared golden fixture must exercise both Generation and Client without copying GRC truth into ConceptWeave or giving ConceptWeave direct GRC application-table access. @@ -77,7 +77,8 @@ The current digest value object validates the declared `sha256:<64 hex>` identit - treating vector similarity as semantic truth; - copying every external ontology into one CWL namespace; - building a generic LLM gateway or browser crawler; -- claiming digest syntax validation is cryptographic byte verification; +- treating digest syntax validation alone as cryptographic integrity evidence; +- inferring backward compatibility merely because one version number is older; - claiming an emerging draft semantic-layer format is a stable standard. ## 8. Acceptance criteria for the first commercial candidate @@ -91,6 +92,7 @@ The current digest value object validates the declared `sha256:<64 hex>` identit - malformed/hostile source contracts rejected with bounded resource use; - semantic-model release can be reproduced from source receipts and approved proposal receipts; - consumer can validate release schema/version/governance state offline before authoritative use; +- current, explicitly supported legacy, and unknown contract versions have deterministic fail-closed compatibility outcomes; - consumer can deterministically diff admitted releases without provider access or bypassing release admission; -- exact serialized artifact digest verification exists before integrity is claimed; +- exact detached artifact digest verification succeeds only for matching bytes; - buyer can inspect why each published artifact exists and which evidence supported it. From 67132eda0e25d23a4185d4b98f0c6dc3b11e17a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:35:32 +0900 Subject: [PATCH 37/67] test(client): require explicit immutable release supersession --- .../tests/release_supersession.rs | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 crates/conceptweave-client/tests/release_supersession.rs diff --git a/crates/conceptweave-client/tests/release_supersession.rs b/crates/conceptweave-client/tests/release_supersession.rs new file mode 100644 index 00000000..05b7d2bb --- /dev/null +++ b/crates/conceptweave-client/tests/release_supersession.rs @@ -0,0 +1,175 @@ +use conceptweave_client::{ + ReleaseContractError, ReleaseDigest, ReleaseMetadata, ReleaseSupersession, + SemanticRelease, SemanticReleaseClient, SemanticReleaseReference, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:grc-schema-2026-09-01", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "governance_core.control_evidence.control_identifier", + ) + .expect("evidence fixture is valid") +} + +fn digest(hex: char) -> ReleaseDigest { + ReleaseDigest::new(format!("sha256:{}", hex.to_string().repeat(64))) + .expect("digest fixture is valid") +} + +fn release( + release_id: &str, + digest_hex: char, + publication_state: PublicationState, +) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new(release_id, "2.0.0", format!("ontology_{release_id}")) + .expect("metadata fixture is valid"), + TruthStatus::Authoritative, + publication_state, + digest(digest_hex), + vec![evidence()], + vec!["control.evidence".to_owned()], + ) + .expect("release fixture is valid") +} + +#[test] +fn supersession_preserves_exact_immutable_release_references_and_rationale() { + let previous = release( + "semantic_release_2026_09", + 'b', + PublicationState::Published, + ); + let successor = release( + "semantic_release_2026_10", + 'c', + PublicationState::Published, + ); + let declaration = ReleaseSupersession::new( + SemanticReleaseReference::from_release(&previous), + SemanticReleaseReference::from_release(&successor), + "Correct the governed control taxonomy while preserving the prior release.", + ) + .expect("supersession declaration is valid"); + + assert_eq!( + declaration.superseded().release_id(), + "semantic_release_2026_09" + ); + assert_eq!(declaration.superseded().artifact_digest(), previous.artifact_digest()); + assert_eq!( + declaration.successor().release_id(), + "semantic_release_2026_10" + ); + assert_eq!(declaration.successor().artifact_digest(), successor.artifact_digest()); + assert_eq!( + declaration.rationale(), + "Correct the governed control taxonomy while preserving the prior release." + ); +} + +#[test] +fn supersession_rejects_blank_reference_fields_blank_rationale_and_self_supersession() { + assert_eq!( + SemanticReleaseReference::new(" ", digest('b')), + Err(ReleaseContractError::EmptyField("release_reference_id")) + ); + assert_eq!( + ReleaseSupersession::new( + SemanticReleaseReference::new("semantic_release_2026_09", digest('b')) + .expect("reference is valid"), + SemanticReleaseReference::new("semantic_release_2026_10", digest('c')) + .expect("reference is valid"), + "\t", + ), + Err(ReleaseContractError::EmptyField("supersession_rationale")) + ); + assert_eq!( + ReleaseSupersession::new( + SemanticReleaseReference::new("semantic_release_2026_09", digest('b')) + .expect("reference is valid"), + SemanticReleaseReference::new("semantic_release_2026_09", digest('c')) + .expect("reference is valid"), + "replacement", + ), + Err(ReleaseContractError::SelfSupersession( + "semantic_release_2026_09".to_owned() + )) + ); +} + +#[test] +fn client_accepts_only_an_explicit_supersession_bound_to_both_exact_release_identities() { + let client = SemanticReleaseClient::new("2.0.0").expect("client policy is valid"); + let previous = release( + "semantic_release_2026_09", + 'b', + PublicationState::Published, + ); + let successor = release( + "semantic_release_2026_10", + 'c', + PublicationState::Published, + ); + let declaration = ReleaseSupersession::new( + SemanticReleaseReference::from_release(&previous), + SemanticReleaseReference::from_release(&successor), + "superseded by steward-approved correction", + ) + .expect("supersession declaration is valid"); + + assert_eq!( + client.validate_supersession(&declaration, &previous, &successor), + Ok(()) + ); + + let wrong_previous = release( + "semantic_release_2026_08", + 'd', + PublicationState::Published, + ); + assert_eq!( + client.validate_supersession(&declaration, &wrong_previous, &successor), + Err(ReleaseContractError::SupersededReleaseReferenceMismatch) + ); + + let wrong_successor = release( + "semantic_release_2026_11", + 'e', + PublicationState::Published, + ); + assert_eq!( + client.validate_supersession(&declaration, &previous, &wrong_successor), + Err(ReleaseContractError::SuccessorReleaseReferenceMismatch) + ); +} + +#[test] +fn supersession_never_bypasses_authoritative_release_admission() { + let client = SemanticReleaseClient::new("2.0.0").expect("client policy is valid"); + let previous = release( + "semantic_release_2026_09", + 'b', + PublicationState::Reviewed, + ); + let successor = release( + "semantic_release_2026_10", + 'c', + PublicationState::Published, + ); + let declaration = ReleaseSupersession::new( + SemanticReleaseReference::from_release(&previous), + SemanticReleaseReference::from_release(&successor), + "attempted supersession", + ) + .expect("supersession declaration is structurally valid"); + + assert_eq!( + client.validate_supersession(&declaration, &previous, &successor), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }) + ); +} From 2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:37:29 +0900 Subject: [PATCH 38/67] feat(client): bind explicit immutable release supersession --- crates/conceptweave-client/src/lib.rs | 131 ++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index a7213199..b1168292 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -183,6 +183,96 @@ impl SemanticRelease { } } +/// Immutable reference to the exact bytes of one published semantic release. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SemanticReleaseReference { + release_id: String, + artifact_digest: ReleaseDigest, +} + +impl SemanticReleaseReference { + /// Creates an exact release reference from a stable release id and canonical digest. + pub fn new( + release_id: impl Into, + artifact_digest: ReleaseDigest, + ) -> Result { + let release_id = release_id.into(); + require_non_blank(&release_id, "release_reference_id")?; + Ok(Self { + release_id, + artifact_digest, + }) + } + + /// Captures the immutable id-and-digest identity of a release contract. + #[must_use] + pub fn from_release(release: &SemanticRelease) -> Self { + Self { + release_id: release.release_id().to_owned(), + artifact_digest: release.artifact_digest().clone(), + } + } + + /// Returns the referenced stable semantic-release id. + pub fn release_id(&self) -> &str { + &self.release_id + } + + /// Returns the referenced immutable semantic-release artifact digest. + pub fn artifact_digest(&self) -> &ReleaseDigest { + &self.artifact_digest + } +} + +/// Explicit immutable declaration that one release is superseded by another release. +/// +/// Supersession is never inferred from semantic version ordering, timestamps, or diffs. Both +/// references are bound to exact release ids and artifact digests so a correction preserves the +/// prior published release while naming the precise steward-approved successor. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ReleaseSupersession { + superseded: SemanticReleaseReference, + successor: SemanticReleaseReference, + rationale: String, +} + +impl ReleaseSupersession { + /// Creates an explicit supersession declaration between two distinct release identities. + pub fn new( + superseded: SemanticReleaseReference, + successor: SemanticReleaseReference, + rationale: impl Into, + ) -> Result { + let rationale = rationale.into(); + require_non_blank(&rationale, "supersession_rationale")?; + if superseded.release_id() == successor.release_id() { + return Err(ReleaseContractError::SelfSupersession( + superseded.release_id().to_owned(), + )); + } + Ok(Self { + superseded, + successor, + rationale, + }) + } + + /// Returns the exact immutable release reference being superseded. + pub fn superseded(&self) -> &SemanticReleaseReference { + &self.superseded + } + + /// Returns the exact immutable successor release reference. + pub fn successor(&self) -> &SemanticReleaseReference { + &self.successor + } + + /// Returns the explicit steward-facing reason for supersession. + pub fn rationale(&self) -> &str { + &self.rationale + } +} + /// Deterministic concept-level change between two admitted semantic releases. /// /// This value reports only public semantic-contract differences. It does not @@ -385,6 +475,29 @@ impl SemanticReleaseClient { Ok(()) } + /// Validates an explicit immutable supersession declaration between two admitted releases. + /// + /// Both releases must independently pass the normal authoritative-use gate. The declaration + /// must then match each exact release id and artifact digest. No version order, timestamp, + /// content diff, or ontology similarity is treated as implicit supersession evidence. + pub fn validate_supersession( + &self, + declaration: &ReleaseSupersession, + superseded: &SemanticRelease, + successor: &SemanticRelease, + ) -> Result<(), ReleaseContractError> { + self.validate_for_authoritative_use(superseded)?; + self.validate_for_authoritative_use(successor)?; + + if declaration.superseded() != &SemanticReleaseReference::from_release(superseded) { + return Err(ReleaseContractError::SupersededReleaseReferenceMismatch); + } + if declaration.successor() != &SemanticReleaseReference::from_release(successor) { + return Err(ReleaseContractError::SuccessorReleaseReferenceMismatch); + } + Ok(()) + } + /// Compares two admitted releases and reports deterministic concept changes. /// /// Both releases pass the same authoritative-use admission gate before any @@ -449,6 +562,12 @@ pub enum ReleaseContractError { DuplicateConceptId(String), /// The configured current contract version was also supplied as a legacy version. CurrentContractVersionMarkedLegacy(String), + /// A release attempted to supersede the same stable release identity. + SelfSupersession(String), + /// The declared superseded id-and-digest reference does not match the supplied release. + SupersededReleaseReferenceMismatch, + /// The declared successor id-and-digest reference does not match the supplied release. + SuccessorReleaseReferenceMismatch, /// The release uses a contract version this client does not support. UnsupportedContractVersion { /// Current contract version required by the client when no explicit compatibility exists. @@ -491,6 +610,18 @@ impl fmt::Display for ReleaseContractError { formatter, "current semantic release contract version `{contract_version}` cannot also be marked legacy" ), + Self::SelfSupersession(release_id) => write!( + formatter, + "semantic release `{release_id}` cannot supersede itself" + ), + Self::SupersededReleaseReferenceMismatch => write!( + formatter, + "supersession predecessor reference does not match the exact supplied release" + ), + Self::SuccessorReleaseReferenceMismatch => write!( + formatter, + "supersession successor reference does not match the exact supplied release" + ), Self::UnsupportedContractVersion { expected, actual } => write!( formatter, "semantic release contract version `{actual}` is unsupported; current version is `{expected}`" From e04c7bdd5934f175d9e5cd9b3e2ab26802a64e41 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:38:21 +0900 Subject: [PATCH 39/67] test(client): cover exact supersession digest and admission edges --- .../tests/release_supersession.rs | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/crates/conceptweave-client/tests/release_supersession.rs b/crates/conceptweave-client/tests/release_supersession.rs index 05b7d2bb..e23627ba 100644 --- a/crates/conceptweave-client/tests/release_supersession.rs +++ b/crates/conceptweave-client/tests/release_supersession.rs @@ -58,12 +58,18 @@ fn supersession_preserves_exact_immutable_release_references_and_rationale() { declaration.superseded().release_id(), "semantic_release_2026_09" ); - assert_eq!(declaration.superseded().artifact_digest(), previous.artifact_digest()); + assert_eq!( + declaration.superseded().artifact_digest(), + previous.artifact_digest() + ); assert_eq!( declaration.successor().release_id(), "semantic_release_2026_10" ); - assert_eq!(declaration.successor().artifact_digest(), successor.artifact_digest()); + assert_eq!( + declaration.successor().artifact_digest(), + successor.artifact_digest() + ); assert_eq!( declaration.rationale(), "Correct the governed control taxonomy while preserving the prior release." @@ -125,49 +131,65 @@ fn client_accepts_only_an_explicit_supersession_bound_to_both_exact_release_iden Ok(()) ); - let wrong_previous = release( - "semantic_release_2026_08", + let wrong_previous_digest = release( + "semantic_release_2026_09", 'd', PublicationState::Published, ); assert_eq!( - client.validate_supersession(&declaration, &wrong_previous, &successor), + client.validate_supersession(&declaration, &wrong_previous_digest, &successor), Err(ReleaseContractError::SupersededReleaseReferenceMismatch) ); - let wrong_successor = release( - "semantic_release_2026_11", + let wrong_successor_digest = release( + "semantic_release_2026_10", 'e', PublicationState::Published, ); assert_eq!( - client.validate_supersession(&declaration, &previous, &wrong_successor), + client.validate_supersession(&declaration, &previous, &wrong_successor_digest), Err(ReleaseContractError::SuccessorReleaseReferenceMismatch) ); } #[test] -fn supersession_never_bypasses_authoritative_release_admission() { +fn supersession_never_bypasses_either_authoritative_release_admission_gate() { let client = SemanticReleaseClient::new("2.0.0").expect("client policy is valid"); - let previous = release( + let reviewed_previous = release( "semantic_release_2026_09", 'b', PublicationState::Reviewed, ); - let successor = release( + let published_previous = release( + "semantic_release_2026_09", + 'b', + PublicationState::Published, + ); + let published_successor = release( "semantic_release_2026_10", 'c', PublicationState::Published, ); + let reviewed_successor = release( + "semantic_release_2026_10", + 'c', + PublicationState::Reviewed, + ); let declaration = ReleaseSupersession::new( - SemanticReleaseReference::from_release(&previous), - SemanticReleaseReference::from_release(&successor), + SemanticReleaseReference::from_release(&published_previous), + SemanticReleaseReference::from_release(&published_successor), "attempted supersession", ) .expect("supersession declaration is structurally valid"); assert_eq!( - client.validate_supersession(&declaration, &previous, &successor), + client.validate_supersession(&declaration, &reviewed_previous, &published_successor), + Err(ReleaseContractError::ReleaseNotPublished { + actual: PublicationState::Reviewed, + }) + ); + assert_eq!( + client.validate_supersession(&declaration, &published_previous, &reviewed_successor), Err(ReleaseContractError::ReleaseNotPublished { actual: PublicationState::Reviewed, }) From 3e90cf24a6d3d041fed689e06bfefd7c9101d128 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:38:38 +0900 Subject: [PATCH 40/67] test(client): cover supersession errors and current compatibility wording --- .../tests/error_messages.rs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/conceptweave-client/tests/error_messages.rs b/crates/conceptweave-client/tests/error_messages.rs index c10762cb..3fa0c2e4 100644 --- a/crates/conceptweave-client/tests/error_messages.rs +++ b/crates/conceptweave-client/tests/error_messages.rs @@ -28,12 +28,31 @@ fn contract_errors_explain_the_failed_admission_invariant() { ReleaseContractError::DuplicateConceptId("concept.one".to_string()), "semantic release contains duplicate concept id `concept.one`".to_string(), ), + ( + ReleaseContractError::CurrentContractVersionMarkedLegacy("2.0.0".to_string()), + "current semantic release contract version `2.0.0` cannot also be marked legacy" + .to_string(), + ), + ( + ReleaseContractError::SelfSupersession("semantic_release_2026_09".to_string()), + "semantic release `semantic_release_2026_09` cannot supersede itself".to_string(), + ), + ( + ReleaseContractError::SupersededReleaseReferenceMismatch, + "supersession predecessor reference does not match the exact supplied release" + .to_string(), + ), + ( + ReleaseContractError::SuccessorReleaseReferenceMismatch, + "supersession successor reference does not match the exact supplied release" + .to_string(), + ), ( ReleaseContractError::UnsupportedContractVersion { expected: "1.0.0".to_string(), actual: "2.0.0".to_string(), }, - "semantic release contract version `2.0.0` is unsupported; expected `1.0.0`" + "semantic release contract version `2.0.0` is unsupported; current version is `1.0.0`" .to_string(), ), ( From 093551ab0f5fa9c05c96935c0e98162f3141292c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:40:08 +0900 Subject: [PATCH 41/67] docs(adr): keep client boundary proposed and bind supersession decision --- .../0004-semantic-release-client-boundary.md | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/docs/adr/0004-semantic-release-client-boundary.md b/docs/adr/0004-semantic-release-client-boundary.md index ae042e47..d575236c 100644 --- a/docs/adr/0004-semantic-release-client-boundary.md +++ b/docs/adr/0004-semantic-release-client-boundary.md @@ -1,37 +1,35 @@ # ADR 0004 — Semantic-release client boundary -- **Status:** Accepted +- **Status:** Proposed - **Date:** 2026-09-02 - **Decision owners:** ConceptWeave Governance & Publication and Client Consumption bounded contexts +- **Related:** Issue #3, PR #5, `docs/product-technical-gap-baseline.md` ## Context -Issue #3 requires downstream CWL products to consume governed ConceptWeave releases without importing generation internals. The foundation already separates candidate truth from publication state, but a buyer-facing workflow is incomplete until a consumer can reject an incompatible or non-governed release before it is used. +Issue #3 requires downstream CWL products to consume governed ConceptWeave releases without importing generation internals. The foundation separates candidate truth from publication state, but a buyer-facing workflow remains incomplete until a consumer can reject incompatible or non-governed releases, verify exact detached artifact bytes, compare releases, and follow an explicit correction/supersession relation without guessing from version order or timestamps. -A client contract must remain useful offline. LLM/provider availability, generator prompts, persistence state, and foreign application databases cannot be prerequisites for deterministic release admission. Conversely, client-side structural checks must not be confused with publication authority, consuming-product authorization, or cryptographic verification that has not actually occurred. +A client contract must remain useful offline. LLM/provider availability, generator prompts, persistence state, and foreign application databases cannot be prerequisites for deterministic release admission. Conversely, client-side structural checks must not be confused with publication authority, consuming-product authorization, or cryptographic/signature verification that has not actually occurred. + +This ADR remains **Proposed** while PR #5 is Draft and exact-head Product/security/review evidence is incomplete. Implemented code on an unintegrated Draft head is evidence for the decision, not grounds to mark the decision Accepted prematurely. ## Decision -Introduce **Client Consumption** as a supporting bounded context and `conceptweave-client` as its first Rust reference implementation. +Introduce **Client Consumption** as a Supporting Bounded Context and `conceptweave-client` as its Rust reference implementation. -The initial versioned `semantic_release` public contract carries: +The current `semantic_release` public contract carries stable release identity, explicit contract and ontology/model versions, truth/publication state, a canonical declared artifact digest identity, provenance references, and unique stable concept identifiers. `SemanticReleaseClient` admits authoritative use only when the release uses the explicit current contract version or an explicitly configured supported-legacy version and is both `Published` and `Authoritative`. Compatibility is never inferred from semantic-version ordering. -- stable release identity; -- explicit contract and ontology/model versions; -- truth and publication state; -- a declared artifact digest identity; -- provenance references; -- unique stable concept identifiers. +`ReleaseDigest` accepts only canonical `sha256:<64 lowercase hex>` identity. `SemanticReleaseClient::verify_serialized_artifact` separately hashes the exact caller-supplied detached bytes and requires an exact digest match after authoritative-use admission. Digest syntax and byte-integrity evidence therefore remain distinct. -`SemanticReleaseClient` admits authoritative use only when the release contract version exactly matches the supported version and the release is both `Published` and `Authoritative`. The check is deterministic and performs no network, model, database, source-system, or consumer-authorization work. +`SemanticReleaseClient::diff` admits both releases through the same authoritative-use gate and reports deterministic sorted concept additions/removals. Exact concept resolution is deterministic and performs no fuzzy matching or model call. -The public Draft 2020-12 JSON Schema mirrors the structural invariants. `ReleaseDigest` accepts only `sha256:<64 hex>` as the declared digest identity. This is **not** a cryptographic integrity claim: a separate future adapter must hash the exact serialized release bytes and compare that digest before integrity is established. +For corrections, `SemanticReleaseReference` binds one release id to its exact artifact digest. `ReleaseSupersession` names a distinct superseded reference, an exact successor reference, and a nonblank rationale. `validate_supersession` requires both referenced releases to pass ordinary authoritative-use admission and requires both id-and-digest references to match exactly. Supersession is never inferred from version order, timestamp, semantic diff, or ontology similarity, and the prior immutable release is not overwritten. -The generation-to-client seam is a versioned public contract. Client code may use public domain value types such as `TruthStatus`, `PublicationState`, and `EvidenceReference`, but may not import generator-private classes, prompts, provider payloads, persistence tables, or orchestration state. +The generation-to-client seam is a versioned public contract. Client code may use public domain value types such as `TruthStatus`, `PublicationState`, and `EvidenceReference`, but may not import generator-private classes, prompts, provider payloads, persistence tables, Source Observation internals, or orchestration state. Consuming products keep tenant/purpose authorization, business-domain truth, and physical query execution. ConceptWeave returns semantic contracts/query plans; it does not become a foreign product's data plane. -LLM-assisted future `match`, ambiguity explanation, and candidate ranking operations must use `ContextualWisdomLab/contextual-orchestrator`. Their outputs remain candidate/evidence state. `validate`, contract compatibility, digest verification, publication-state checks, and authorization remain deterministic. +LLM-assisted future `match`, ambiguity explanation, and candidate ranking operations must use `ContextualWisdomLab/contextual-orchestrator`. Their outputs remain candidate/evidence state. Admission, compatibility, digest verification, supersession validation, publication-state checks, and authorization remain deterministic. ## Consequences @@ -40,26 +38,40 @@ LLM-assisted future `match`, ambiguity explanation, and candidate ranking operat - consumers can fail closed before authoritative use without an LLM provider; - stable release contracts prevent generator-private implementation leakage; - truth/publication authority remains explicit across repository boundaries; -- digest syntax and actual integrity verification cannot be accidentally conflated; +- digest syntax and actual byte verification cannot be conflated; +- explicit supported-legacy policy avoids accidental version-order heuristics; +- corrections preserve immutable predecessor releases and bind the exact successor by id plus digest; - GRC and other downstream consumers can build ACLs against one stable seam. ### Costs and deferred work -- current compatibility is exact-version only; older-supported compatibility and deprecation policy remain #3 work; -- current digest value validates identity syntax only; exact serialized-byte hashing/signature verification remains required before integrity claims; -- release diff, supersession/staleness policy, match/resolve/explain/query-plan operations remain #3 work; -- language-neutral generated bindings remain deferred until the JSON contract is stable enough to justify them. +- the Rust supersession contract does not yet have a finalized language-neutral supersession JSON Schema or generated bindings; +- signature/provenance-chain verification remains deferred until Governance & Publication defines a stable signing contract; +- typed relation/mapping/dimension/measure resolution, match/align/explain, and semantic query-plan operations remain Issue #3 work; +- GRC reference-client fixtures remain required before buyer-facing integration readiness; +- this ADR cannot advance to Accepted until the stacked implementation is integrated and current-head deterministic/security/review evidence is terminal. ## Alternatives rejected 1. **Let consumers import generator internals.** Rejected because it couples downstream products to prompts/adapters/persistence and destroys the reuse boundary. -2. **Require an LLM call to decide release usability.** Rejected because compatibility, governance state, and integrity are deterministic security controls. +2. **Require an LLM call to decide release usability.** Rejected because compatibility, governance state, digest verification, and explicit supersession are deterministic security/data-integrity controls. 3. **Treat a well-shaped digest string as proof of artifact integrity.** Rejected because syntax validation does not hash bytes. -4. **Move downstream authorization into ConceptWeave.** Rejected because tenant/purpose authorization belongs to each consuming product and its identity/control plane. +4. **Infer compatibility or supersession from version ordering/timestamps.** Rejected because neither proves compatibility nor steward-approved replacement and would create hidden heuristics. +5. **Overwrite a published release in place when corrected.** Rejected because published semantic truth is immutable; correction creates a distinct successor and explicit supersession evidence. +6. **Move downstream authorization into ConceptWeave.** Rejected because tenant/purpose authorization belongs to each consuming product and its identity/control plane. + +## Verification evidence on the active branch + +- Existing Rust integration tests cover authoritative admission, compatibility, non-Published/non-Authoritative states, provenance/identity requirements, duplicate concepts, digest syntax, exact byte verification, diff, and exact concept resolution. +- Test-first supersession commit `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` introduced an API that did not yet exist and required immutable id+digest predecessor/successor references, rationale, self-supersession rejection, exact-reference validation, and ordinary authoritative admission. +- Production commit `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements that bounded contract. Follow-up edge coverage binds mismatch checks to digest as well as id and exercises both predecessor and successor admission paths. +- Error-message coverage includes new supersession failures and reconciles the explicit compatibility wording. +- Hosted exact-head Product evidence is still required on the final unchanged documentation head; queued/predecessor results are not GREEN. -## Verification +## Follow-up / acceptance for Accepted status -- Rust integration tests cover authoritative admission, unsupported versions, non-Published and non-Authoritative states, provenance/identity requirements, duplicate concepts, and digest syntax. -- Error-message tests keep failures actionable. -- JSON Schema fixtures cover valid release, published/non-authoritative rejection, duplicate concept rejection, and malformed digest rejection. -- Product CI validates both Rust and JSON contracts on the exact PR head. +1. Obtain exact-head fmt/Clippy/tests/rustdoc/100% owned coverage and public-contract validation on the final PR #5 head. +2. Integrate the foundation prerequisite, cleanly restack PR #5, and rerun every then-required exact-head workflow. +3. Resolve all valid current-head review findings and satisfy ordinary governance without self-approval or routine bypass. +4. Define a language-neutral supersession/publication receipt contract before generated bindings or cross-language release claims. +5. Prove the seam with an anonymized GRC-shaped reference-client fixture and no cross-service application-table access. From 606bc48788d7b8214179b25d784875c4f7d0a81a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:40:21 +0900 Subject: [PATCH 42/67] docs(adr): mark client boundary proposed while draft --- docs/adr/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index e10d8131..0d32a43c 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -3,4 +3,4 @@ - [ADR 0001 — Product and bounded-context boundary](0001-product-boundary.md) - [ADR 0002 — Evidence, truth, and publication lifecycle](0002-truth-publication-lifecycle.md) - [ADR 0003 — Standards and LLM engineering boundary](0003-standards-llm-boundary.md) -- [ADR 0004 — Semantic-release client boundary](0004-semantic-release-client-boundary.md) +- [ADR 0004 — Semantic-release client boundary](0004-semantic-release-client-boundary.md) — Proposed From 1475614e19d03d06719a2c0ee1dd37b32e7451e9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:40:40 +0900 Subject: [PATCH 43/67] docs(changelog): record explicit immutable release supersession --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 575e56f5..882a1d4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to ConceptWeave are documented here. - Deterministic offline semantic-release diff that first applies the same authoritative-use admission policy, then reports stable previous/current release identity and sorted added/removed concept identifiers without network or model calls. - Exact offline SHA-256 verification of caller-supplied serialized semantic-release bytes, with typed digest-mismatch evidence and the same fail-closed authoritative-use admission gate. - Explicit semantic-release compatibility policy that distinguishes the current contract version, caller-declared supported legacy versions, and unknown versions without inferring compatibility from version ordering; supported legacy releases still pass the same Published/Authoritative gate. +- Explicit immutable semantic-release supersession references that bind predecessor and successor release ids to their exact artifact digests, require a rationale, reject self-supersession, and validate both releases through the ordinary authoritative-use gate without inferring replacement from version order or timestamps. - Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. - Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. @@ -25,4 +26,5 @@ All notable changes to ConceptWeave are documented here. - Release diff validates both compared releases through the same fail-closed authoritative-use gate so comparison cannot bypass contract-version, publication-state, or truth-status policy. - Serialized-artifact integrity verification first applies authoritative-use admission, then computes SHA-256 over the exact supplied bytes and rejects any mismatch with the declared release digest. - Digest syntax validation remains distinct from byte verification so a syntactically valid digest is never treated as proof that serialized content matches it. +- Supersession validation requires exact predecessor/successor id-and-digest references and leaves the prior published release immutable; a correction is not inferred from ordering, timestamps, or semantic similarity. - Unsafe Rust is forbidden in the core domain and client crates. From 8e9a58dcb96e4bddf097b0032517381bac815fc6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:41:08 +0900 Subject: [PATCH 44/67] docs(architecture): define immutable client supersession boundary --- ARCHITECTURE.md | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0ae65f42..89e0f073 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -29,11 +29,11 @@ flowchart LR | Source Observation | Supporting | immutable observations, parser receipts, evidence locations | source-system business truth | | Semantic Discovery | Core | candidate generation and evidence binding | publication authority | | Model Validation | Supporting | deterministic validation reports | human review decisions | -| Governance & Publication | Core | proposal lifecycle, review receipts, releases, supersession | catalog/search runtime | -| Client Consumption | Supporting | release admission, compatibility, future diff/match/resolve/query-plan contracts | generator internals, consumer authorization, physical query execution | +| Governance & Publication | Core | proposal lifecycle, review receipts, releases, supersession authority | catalog/search runtime | +| Client Consumption | Supporting | release admission, compatibility, exact byte verification, diff/resolution, explicit immutable supersession validation, future match/query-plan contracts | generator internals, consumer authorization, publication authority, physical query execution | | Interoperability | Supporting | versioned import/export and ACL adapters | foreign product internals | -The generation-to-client dependency crosses only versioned public release contracts. Client code may reuse public domain value types, but it must not import generator-private adapters, prompts, persistence tables, or orchestration state. +The generation-to-client dependency crosses only versioned public release contracts. Client code may reuse public domain value types, but it must not import generator-private adapters, prompts, persistence tables, Source Observation internals, or orchestration state. ## Aggregate and value-object boundaries @@ -47,11 +47,19 @@ Planned Governance & Publication aggregate for immutable publication. The curren ### ReleaseDigest -Client value object for a declared `sha256:<64 hex>` digest identity. It validates digest syntax only. Exact detached artifact bytes must be hashed and compared before integrity is claimed. +Client value object for a declared canonical `sha256:<64 lowercase hex>` digest identity. It validates digest syntax only. Exact detached artifact bytes must be hashed and compared before integrity is claimed. + +### SemanticReleaseReference + +Client value object that binds a stable semantic-release id to its exact artifact digest. It is an immutable coordinate for published release identity and avoids treating a mutable name or version number alone as sufficient supersession evidence. + +### ReleaseSupersession + +Client-visible immutable declaration naming an exact predecessor reference, exact successor reference, and nonblank rationale. It rejects self-supersession. Client validation requires both releases to pass normal Published + Authoritative compatibility admission and both id+digest references to match exactly. The declaration does not mutate either release and never infers replacement from version ordering, timestamps, diff size, or semantic similarity. Governance & Publication remains the authority that creates the eventual publication/supersession receipt; the Client only validates the consumer-visible contract. ### SemanticReleaseClient -A stateless domain service in Client Consumption. Its compatibility policy has one explicit current contract version and an explicit set of supported legacy versions; it never infers compatibility from semantic-version ordering. Unknown versions fail closed. Current and supported-legacy releases pass the same `Published` plus `Authoritative` gate before resolution, diff, or artifact verification. It performs no network, LLM, database, tenant-authorization, or physical-query work. +A stateless domain service in Client Consumption. Its compatibility policy has one explicit current contract version and an explicit set of supported legacy versions; it never infers compatibility from semantic-version ordering. Unknown versions fail closed. Current and supported-legacy releases pass the same `Published` plus `Authoritative` gate before resolution, diff, artifact verification, or supersession validation. It performs no network, LLM, database, tenant-authorization, publication-decision, or physical-query work. ## Truth model @@ -59,10 +67,10 @@ A stateless domain service in Client Consumption. Its compatibility policy has o - `inferred`: derived candidate; - `proposed`: submitted for governance; - `authoritative`: explicitly reviewed and published; -- `superseded`: formerly authoritative and replaced; +- `superseded`: formerly authoritative and replaced through explicit release evidence; - `rejected`: explicitly rejected. -Truth status and publication workflow are distinct. A source observation can be authoritative in its source domain without making an inferred semantic interpretation authoritative. Client admission fails closed rather than coercing these states. +Truth status and publication workflow are distinct. A source observation can be authoritative in its source domain without making an inferred semantic interpretation authoritative. Client admission fails closed rather than coercing these states. Supersession preserves the immutable prior release rather than overwriting it. ## Integration boundaries @@ -80,13 +88,15 @@ No direct cross-service application-table SQL is permitted. ```text crates/ conceptweave-domain/ # Core candidate/evidence lifecycle contracts - conceptweave-client/ # Offline release admission and compatibility boundary + conceptweave-client/ # Offline release admission, compatibility, integrity and supersession validation contracts/ # Versioned public JSON Schemas and fixtures docs/ - adr/ # Binding architecture decisions + adr/ # Proposed/accepted architecture decisions doctoring/ # Standards/research evidence scripts/ # Deterministic repository-quality helpers .github/workflows/ # CI evidence ``` Adapters and application services are added only when their bounded responsibility exists; generic `utils`, `helpers`, or `services` dumping grounds are prohibited. + +ADR 0004 remains Proposed while PR #5 is Draft and current-head checks/governance are incomplete; implementation on an unintegrated head is not sufficient to mark the architecture decision Accepted. From 28fb363025344e2e1a3ee8fc08a40779db3cf13f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:41:36 +0900 Subject: [PATCH 45/67] docs(prd): require immutable explicit release supersession --- docs/PRD.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/PRD.md b/docs/PRD.md index 6a30dc4a..d199a757 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -6,7 +6,7 @@ ConceptWeave converts heterogeneous enterprise evidence into a governed ontology ## 2. Buyer problem -Enterprise teams repeatedly hand-build business glossaries, ontologies, metric definitions, semantic mappings, and data relationships from database schemas, API contracts, documents, and tribal knowledge. The work is slow, inconsistent across tools, difficult to audit, and unsafe to delegate entirely to an LLM because inferred semantics can be plausible but wrong. Even after a model is published, consumers need a deterministic way to determine whether a release is compatible, governed, and safe to use. +Enterprise teams repeatedly hand-build business glossaries, ontologies, metric definitions, semantic mappings, and data relationships from database schemas, API contracts, documents, and tribal knowledge. The work is slow, inconsistent across tools, difficult to audit, and unsafe to delegate entirely to an LLM because inferred semantics can be plausible but wrong. Even after a model is published, consumers need a deterministic way to determine whether a release is compatible, governed, immutable, superseded by an explicit successor, and safe to use. ## 3. Primary buyers and users @@ -44,7 +44,7 @@ A candidate cannot become authoritative solely because an LLM or automated extra ### FR-6 Publication -Publish versioned artifacts for ontology and semantic-layer consumers while retaining the exact input snapshot and proposal/review receipts that produced the release. +Publish versioned immutable artifacts for ontology and semantic-layer consumers while retaining the exact input snapshot and proposal/review receipts that produced the release. A correction must create a distinct successor release rather than overwrite a published artifact in place. Supersession authority belongs to Governance & Publication and must produce an explicit predecessor/successor receipt; version ordering or timestamps alone are never replacement evidence. ### FR-7 Interoperability @@ -62,9 +62,11 @@ An admitted client can compare two releases deterministically without contacting The digest value object validates canonical `sha256:<64 lowercase hex>` identity syntax. Cryptographic integrity is a separate operation: `SemanticReleaseClient::verify_serialized_artifact` first applies authoritative-use admission, then hashes the exact caller-supplied detached artifact bytes and requires an exact digest match. Syntax validity alone is never integrity evidence. +A client can also validate an explicit immutable supersession declaration. `SemanticReleaseReference` binds a release id to its exact artifact digest. `ReleaseSupersession` names distinct predecessor/successor references plus a nonblank rationale, rejects self-supersession, and `validate_supersession` requires both releases to pass ordinary authoritative-use admission and both id+digest coordinates to match exactly. This is consumer-side validation only; it does not grant publication authority or infer supersession from version order, time, diff, or semantic similarity. A language-neutral supersession/publication-receipt schema remains required before cross-language client completeness is claimed. + ## 6. First Generation ↔ Client vertical -`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission/diff/integrity verification -> consuming-product ACL/query boundary`. +`relational schema snapshot -> observed tables/columns/foreign keys -> concept/relation/dimension/measure/mapping candidates -> evidence-bound validation -> steward review -> immutable semantic_release -> offline client admission/diff/integrity/supersession validation -> consuming-product ACL/query boundary`. `ContextualWisdomLab/governance-risk-compliance` is the first reference source/client scenario, not a special-case algorithm. A shared golden fixture must exercise both Generation and Client without copying GRC truth into ConceptWeave or giving ConceptWeave direct GRC application-table access. @@ -79,6 +81,8 @@ The digest value object validates canonical `sha256:<64 lowercase hex>` identity - building a generic LLM gateway or browser crawler; - treating digest syntax validation alone as cryptographic integrity evidence; - inferring backward compatibility merely because one version number is older; +- inferring supersession from version order, timestamps, semantic similarity, or diff size; +- overwriting a published semantic release in place; - claiming an emerging draft semantic-layer format is a stable standard. ## 8. Acceptance criteria for the first commercial candidate @@ -95,4 +99,6 @@ The digest value object validates canonical `sha256:<64 lowercase hex>` identity - current, explicitly supported legacy, and unknown contract versions have deterministic fail-closed compatibility outcomes; - consumer can deterministically diff admitted releases without provider access or bypassing release admission; - exact detached artifact digest verification succeeds only for matching bytes; -- buyer can inspect why each published artifact exists and which evidence supported it. +- corrections preserve the immutable predecessor and identify an explicit distinct successor by exact release id plus digest rather than version-order inference; +- a language-neutral supersession/publication receipt is validated before cross-language release consumption is called complete; +- buyer can inspect why each published artifact exists, which evidence supported it, and why/when it was explicitly superseded. From 9688dde08368a9324d64abe25122036719dcc1fd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:42:21 +0900 Subject: [PATCH 46/67] docs(gap): reconcile client supersession and source-port exact evidence --- docs/product-technical-gap-baseline.md | 30 +++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 6b031b25..6351298a 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -10,51 +10,53 @@ Only the repository bootstrap README exists before the foundation PR. No product | Area | Owner | Status | Evidence / action / next verification | | --- | --- | --- | --- | -| Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against the exact PR #1 head before merge. | +| Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` before merge. | | Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated while public transition APIs fail closed at steward-reviewed/publication boundaries; Draft 2020-12 candidate schema enforces public candidate shape and Published -> Authoritative consistency. | | Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | | Quality gate | ConceptWeave | ACTIVE_PR | Exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` has Product run `33527150325` and SAST run `33527150417` terminal success. | | Security/test/operability | ConceptWeave + central `.github` | CONTROL_PLANE_BLOCKED | Security Scan run `33527150445` reached exact checkout; dependency-review job `100059571813` failed at `Check dependency review support`, so the pinned Dependency Review step was skipped. OSV/Trivy/Scorecard succeeded but are not substitutes. | -| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; no self-approval or routine admin bypass is accepted. | +| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; fresh foundation threads are resolved but no qualifying APPROVED review exists. No self-approval or routine admin bypass is accepted. | ## Active Client Consumption slice — PR #5 / Issue #3 -PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. The canonical exact head is the live GitHub PR head; editing this file changes that SHA, so check evidence is valid only for the later unchanged branch head. +PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. It remains Draft. The canonical exact head is the live GitHub PR head; editing this file changes that SHA, so check evidence is valid only for the later unchanged branch head. | Gap | Owner | Status | Evidence | Action | Next verification | | --- | --- | --- | --- | --- | --- | | Offline release admission | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `SemanticReleaseClient` requires explicit compatibility plus Published + Authoritative and remains provider/network independent. | Preserve downstream tenant/purpose authorization and physical execution boundaries. | Exact-head Rust tests/Clippy/docs/coverage. | | Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance and unique concept IDs. | Keep language-neutral contract stable before generated bindings. | Exact-head AJV + Rust contract parity. | -| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first byte-verification lineage culminates in `verify_serialized_artifact`, which hashes exact caller-supplied bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. | Add signature/provenance verification only when the publication design defines a stable signing contract. | Exact-head tamper/mutation fixtures and Product run. | +| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `verify_serialized_artifact` hashes exact caller-supplied bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. | Add signature/provenance-chain verification only when publication defines a stable signing contract. | Exact-head tamper/mutation fixtures and Product run. | | Release diff | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Deterministic `diff` admits both releases through the same governance/compatibility gate and reports sorted added/removed concept IDs. | Extend only when typed relation/mapping/measure diff contracts exist. | Golden added/removed fixtures and exact-head Product run. | | Exact concept resolution | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `resolve_concept` performs exact deterministic lookup after authoritative-use admission; no fuzzy/LLM inference. | Add relation and physical-mapping resolution next. | Exact-head edge cases for unknown/blank IDs. | -| Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first commit `091c36b24330671952de378d3596afcde5f62351` specifies Current / SupportedLegacy / Unsupported behavior, same authoritative gate for supported legacy releases, and fail-closed invalid policy. Production commit `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements `ContractVersionCompatibility` plus explicit current/legacy policy without inferring version ordering. | Add explicit deprecation/supersession semantics; do not treat arbitrary older versions as supported. | Hosted exact-head Product/Clippy/tests on the final unchanged documentation head. | +| Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first `091c36b24330671952de378d3596afcde5f62351`; production `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements Current / SupportedLegacy / Unsupported without version-order inference. | Keep support explicit and bounded; unknown versions remain fail closed. | Hosted exact-head Product/Clippy/tests on final unchanged head. | +| Explicit immutable supersession | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | Test-first `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` required exact predecessor/successor id+digest references, nonblank rationale, self-supersession rejection, and ordinary authoritative-use admission. Production `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements `SemanticReleaseReference`, `ReleaseSupersession`, and `validate_supersession`; follow-up tests exercise digest mismatch and both predecessor/successor admission paths. | Add a language-neutral supersession/publication-receipt schema before cross-language completeness; do not infer replacement from version order/time/diff. ADR 0004 stays Proposed while PR #5 is Draft/checks incomplete. | Exact-head fmt/Clippy/tests/rustdoc/100% coverage plus public-contract parity. | | Match / align / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research traceability defines retrieve/filter/match constraints. | Deterministic candidate retrieval first; optional LLM only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | | Query-plan contract | Client Consumption | GAP | Issue #3 requires semantic plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | | Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution downstream. | Cross-tenant/purpose denial tests in each consumer. | ## Parallel Source Observation slice — PR #6 / Issue #2 -PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Live repository evidence on 2026-09-02 shows it now preserves immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, and explicit PostgreSQL 18 FK validation/enforcement state. Its current exact head and checks must be read from PR #6 before integration; sibling predecessor evidence does not transfer into this branch. The next Generation gap remains a bounded read-only PostgreSQL adapter with cancellation/timeout/resource limits and a frozen anonymized GRC fixture. +PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. At the latest live read in this commercialization iteration, PR #6 exact head `e56054cdce716a91759294b1993b31a1ca93ed57` preserves immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the new provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, and typed source-disappearance/resource-limit outcomes. Its exact-head Product run `33609118662` was queued before execution and therefore non-passing. A concrete Rust read-only PostgreSQL adapter remains open. ## Central control-plane evidence -- `ContextualWisdomLab/.github#712` owns hosted-runner acquisition/queue health; queued jobs before checkout remain incomplete evidence. -- `ContextualWisdomLab/.github#810` owns authoritative Dependency Review availability/configuration. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. -- `ContextualWisdomLab/.github#772` owns the solo-maintainer approval-governance defect. Live ruleset `18156473` still requires one approving review while `required_reviewers=[]`; self-approval/model-as-human/routine bypass are prohibited. -- `ContextualWisdomLab/.github#1219` owns stacked-PR central-review throughput. Leaf repositories must not duplicate the review scheduler. +- `ContextualWisdomLab/.github#712` remains open and owns hosted-runner acquisition/queue health; queued jobs before checkout remain incomplete evidence. +- `ContextualWisdomLab/.github#810` remains open and confirms the central fail-open source defect is repaired while authoritative public non-fork Dependency Review availability/configuration is still unresolved. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. +- `ContextualWisdomLab/.github#772` remains open and owns the solo-maintainer approval-governance defect. Live ruleset `18156473` still has `required_approving_review_count: 1`, `required_reviewers: []`, thread resolution, required central workflows, deletion/non-fast-forward protection, and OrganizationAdmin bypass; self-approval/model-as-human/routine bypass are prohibited. +- `ContextualWisdomLab/.github#1219` remains open and owns stacked-PR central-review throughput. Leaf repositories must not duplicate the review scheduler. +- `.github` PR #1150 remains the open canonical read-only Actions queue-health evidence implementation; do not duplicate its collector. ## Remaining P0 product gaps -1. **Source Observation adapter** — real bounded PostgreSQL introspection, immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen GRC fixture. +1. **Source Observation adapter** — implement the new bounded source port with a real Rust read-only PostgreSQL adapter, immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen anonymized GRC fixture. 2. **Observation-to-candidate provenance** — exact source receipt plus discovery method/proposal receipt for every generated candidate. 3. **Ontology induction** — deterministic observations plus `contextual-orchestrator` structured candidate generation for concepts, taxonomy and non-taxonomic relations. 4. **Semantic-layer induction** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts. 5. **Validation engine** — RDF/OWL/SKOS/SHACL publication validation, consistency checks, duplicate/conflict detection and bounded reasoning. -6. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, immutable releases, transactional outbox and temporal history where warranted. +6. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, immutable releases, explicit supersession/publication receipts, transactional outbox and temporal history where warranted. 7. **Review workflow** — Keyverse tenant/role/purpose context, steward review, maker-checker where required, stale-decision protection and immutable publication receipt. 8. **Publication adapters** — OWL/RDFS/SKOS/SHACL/JSON-LD and version-bound Apache Ossie export. -9. **Client completion** — deprecation/supersession semantics, relation/mapping/dimension/measure resolution, signature/provenance contract, research-backed match/align/explain, and semantic query-plan API. +9. **Client completion** — language-neutral supersession/publication receipt, relation/mapping/dimension/measure resolution, signature/provenance contract, research-backed match/align/explain, semantic query-plan API, and GRC reference fixtures. 10. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC and EA through published contracts only. 11. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility and multilingual cases. 12. **Observability/release** — shared OpenTelemetry bootstrap, structured security events, SBOM/provenance/signing, backup/restore and protected release evidence. @@ -64,6 +66,8 @@ PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Live repositor - No generic `utils/helpers/services/common` domain buckets are permitted. - Adapters remain outside owned domain/client/source-observation contracts. - Client Consumption consumes versioned public release contracts only, never generator-private implementation or persistence. +- Supersession validation is a Client Consumption contract; authority to issue the governed supersession/publication receipt remains Governance & Publication. +- Published releases are immutable; correction creates a distinct successor and preserves the predecessor. - Source Observation preserves source evidence but does not infer semantic authority. - Foreign product DTOs require Anti-Corruption Layers. - `semantic-data-portal` remains catalog/governance/consumption plane, not ConceptWeave persistence. From 143506eb66b6904b770a628ac793af2253559df2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 17:46:42 +0900 Subject: [PATCH 47/67] test(client): require language-neutral supersession contract --- .github/workflows/product.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index 9b370b32..2d5b634b 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -109,6 +109,24 @@ jobs: -s contracts/semantic-release.schema.json \ -d contracts/fixtures/semantic-release.invalid-uppercase-digest.json \ --invalid + npx --yes ajv-cli@5.0.0 compile \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.valid.json \ + --valid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.invalid-digest.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.invalid-rationale.json \ + --invalid - name: Lockfile freshness run: | From 0c32a7b55d3c687ab76cee789962866573496ba1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 02:56:22 +0900 Subject: [PATCH 48/67] style(client): apply rustfmt after hosted RED --- crates/conceptweave-client/src/lib.rs | 5 +- .../tests/release_compatibility.rs | 5 +- .../tests/release_supersession.rs | 66 ++++--------------- 3 files changed, 19 insertions(+), 57 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index b1168292..0e8fb8c6 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -347,10 +347,7 @@ impl SemanticReleaseClient { let mut validated_legacy_versions = BTreeSet::new(); for legacy_version in supported_legacy_contract_versions { - require_non_blank( - &legacy_version, - "supported_legacy_contract_version", - )?; + require_non_blank(&legacy_version, "supported_legacy_contract_version")?; if legacy_version == supported_contract_version { return Err(ReleaseContractError::CurrentContractVersionMarkedLegacy( legacy_version, diff --git a/crates/conceptweave-client/tests/release_compatibility.rs b/crates/conceptweave-client/tests/release_compatibility.rs index 824af8ec..382be413 100644 --- a/crates/conceptweave-client/tests/release_compatibility.rs +++ b/crates/conceptweave-client/tests/release_compatibility.rs @@ -63,7 +63,10 @@ fn supported_legacy_release_passes_the_same_authoritative_use_gate() { ) .expect("explicit compatibility policy is valid"); - assert_eq!(client.validate_for_authoritative_use(&release("1.0.0")), Ok(())); + assert_eq!( + client.validate_for_authoritative_use(&release("1.0.0")), + Ok(()) + ); } #[test] diff --git a/crates/conceptweave-client/tests/release_supersession.rs b/crates/conceptweave-client/tests/release_supersession.rs index e23627ba..b88a9282 100644 --- a/crates/conceptweave-client/tests/release_supersession.rs +++ b/crates/conceptweave-client/tests/release_supersession.rs @@ -1,6 +1,6 @@ use conceptweave_client::{ - ReleaseContractError, ReleaseDigest, ReleaseMetadata, ReleaseSupersession, - SemanticRelease, SemanticReleaseClient, SemanticReleaseReference, + ReleaseContractError, ReleaseDigest, ReleaseMetadata, ReleaseSupersession, SemanticRelease, + SemanticReleaseClient, SemanticReleaseReference, }; use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; @@ -37,16 +37,8 @@ fn release( #[test] fn supersession_preserves_exact_immutable_release_references_and_rationale() { - let previous = release( - "semantic_release_2026_09", - 'b', - PublicationState::Published, - ); - let successor = release( - "semantic_release_2026_10", - 'c', - PublicationState::Published, - ); + let previous = release("semantic_release_2026_09", 'b', PublicationState::Published); + let successor = release("semantic_release_2026_10", 'c', PublicationState::Published); let declaration = ReleaseSupersession::new( SemanticReleaseReference::from_release(&previous), SemanticReleaseReference::from_release(&successor), @@ -109,16 +101,8 @@ fn supersession_rejects_blank_reference_fields_blank_rationale_and_self_superses #[test] fn client_accepts_only_an_explicit_supersession_bound_to_both_exact_release_identities() { let client = SemanticReleaseClient::new("2.0.0").expect("client policy is valid"); - let previous = release( - "semantic_release_2026_09", - 'b', - PublicationState::Published, - ); - let successor = release( - "semantic_release_2026_10", - 'c', - PublicationState::Published, - ); + let previous = release("semantic_release_2026_09", 'b', PublicationState::Published); + let successor = release("semantic_release_2026_10", 'c', PublicationState::Published); let declaration = ReleaseSupersession::new( SemanticReleaseReference::from_release(&previous), SemanticReleaseReference::from_release(&successor), @@ -131,21 +115,15 @@ fn client_accepts_only_an_explicit_supersession_bound_to_both_exact_release_iden Ok(()) ); - let wrong_previous_digest = release( - "semantic_release_2026_09", - 'd', - PublicationState::Published, - ); + let wrong_previous_digest = + release("semantic_release_2026_09", 'd', PublicationState::Published); assert_eq!( client.validate_supersession(&declaration, &wrong_previous_digest, &successor), Err(ReleaseContractError::SupersededReleaseReferenceMismatch) ); - let wrong_successor_digest = release( - "semantic_release_2026_10", - 'e', - PublicationState::Published, - ); + let wrong_successor_digest = + release("semantic_release_2026_10", 'e', PublicationState::Published); assert_eq!( client.validate_supersession(&declaration, &previous, &wrong_successor_digest), Err(ReleaseContractError::SuccessorReleaseReferenceMismatch) @@ -155,26 +133,10 @@ fn client_accepts_only_an_explicit_supersession_bound_to_both_exact_release_iden #[test] fn supersession_never_bypasses_either_authoritative_release_admission_gate() { let client = SemanticReleaseClient::new("2.0.0").expect("client policy is valid"); - let reviewed_previous = release( - "semantic_release_2026_09", - 'b', - PublicationState::Reviewed, - ); - let published_previous = release( - "semantic_release_2026_09", - 'b', - PublicationState::Published, - ); - let published_successor = release( - "semantic_release_2026_10", - 'c', - PublicationState::Published, - ); - let reviewed_successor = release( - "semantic_release_2026_10", - 'c', - PublicationState::Reviewed, - ); + let reviewed_previous = release("semantic_release_2026_09", 'b', PublicationState::Reviewed); + let published_previous = release("semantic_release_2026_09", 'b', PublicationState::Published); + let published_successor = release("semantic_release_2026_10", 'c', PublicationState::Published); + let reviewed_successor = release("semantic_release_2026_10", 'c', PublicationState::Reviewed); let declaration = ReleaseSupersession::new( SemanticReleaseReference::from_release(&published_previous), SemanticReleaseReference::from_release(&published_successor), From 9c278598001c502a733100d11e901538c3dc2677 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 16:51:18 +0900 Subject: [PATCH 49/67] fix(client): verify detached semantic artifacts --- crates/conceptweave-client/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 0e8fb8c6..f852d319 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -15,9 +15,9 @@ use std::collections::BTreeSet; /// A validated content-digest identity carried by a semantic release. /// /// The current contract accepts only the canonical `sha256:<64 lowercase hex>` -/// shape. This value object validates digest identity syntax; exact serialized -/// bytes are cryptographically verified by -/// [`SemanticReleaseClient::verify_serialized_artifact`]. +/// shape. This value object validates digest identity syntax; exact detached +/// artifact bytes are cryptographically verified by +/// [`SemanticReleaseClient::verify_detached_artifact`]. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ReleaseDigest(String); @@ -438,13 +438,13 @@ impl SemanticReleaseClient { .find(|candidate| *candidate == concept_id)) } - /// Verifies the SHA-256 digest of exact serialized semantic-release bytes. + /// Verifies the SHA-256 digest of exact detached semantic-artifact bytes. /// /// The release must first satisfy the same authoritative-use admission gate - /// as other Client operations. The caller supplies the exact bytes whose - /// identity is declared by [`SemanticRelease::artifact_digest`]; this method - /// performs no network access, parsing, provider call, or source-system read. - pub fn verify_serialized_artifact( + /// as other Client operations. The caller supplies the exact detached bytes + /// whose identity is declared by [`SemanticRelease::artifact_digest`]; this + /// method performs no network access, parsing, provider call, or source-system read. + pub fn verify_detached_artifact( &self, release: &SemanticRelease, artifact_bytes: &[u8], @@ -546,7 +546,7 @@ pub enum ReleaseContractError { EmptyField(&'static str), /// The declared release digest is not canonical `sha256:<64 lowercase hex>`. InvalidDigest, - /// Exact serialized bytes do not match the digest declared by the release. + /// Exact detached semantic-artifact bytes do not match the digest declared by the release. ArtifactDigestMismatch { /// Digest coordinate declared by the semantic release. declared: String, From 5bdb873f97aa663e413c12f572df2b92143344a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 18:49:35 +0900 Subject: [PATCH 50/67] test(client): pin detached artifact documentation --- .../tests/documentation_contract.rs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 crates/conceptweave-client/tests/documentation_contract.rs diff --git a/crates/conceptweave-client/tests/documentation_contract.rs b/crates/conceptweave-client/tests/documentation_contract.rs new file mode 100644 index 00000000..1ce94b97 --- /dev/null +++ b/crates/conceptweave-client/tests/documentation_contract.rs @@ -0,0 +1,45 @@ +//! Keep public Client Consumption documentation aligned with the Rust API. + +const PRD: &str = include_str!("../../../docs/PRD.md"); +const TRD: &str = include_str!("../../../docs/TRD.md"); +const UML: &str = include_str!("../../../docs/UML.md"); +const ADR: &str = include_str!("../../../docs/adr/0004-semantic-release-client-boundary.md"); +const GAP_BASELINE: &str = include_str!("../../../docs/product-technical-gap-baseline.md"); +const TEST_STRATEGY: &str = include_str!("../../../TEST_STRATEGY.md"); +const SECURITY: &str = include_str!("../../../SECURITY.md"); + +#[test] +fn retired_serialized_artifact_api_is_absent_from_public_docs() { + for (name, document) in [ + ("PRD", PRD), + ("TRD", TRD), + ("UML", UML), + ("ADR 0004", ADR), + ("gap baseline", GAP_BASELINE), + ("test strategy", TEST_STRATEGY), + ("security", SECURITY), + ] { + assert!( + !document.contains("verify_serialized_artifact"), + "{name} still names the retired serialized-artifact API" + ); + } +} + +#[test] +fn detached_artifact_integrity_is_documented_as_current_behavior() { + for (name, document) in [ + ("PRD", PRD), + ("TRD", TRD), + ("UML", UML), + ("ADR 0004", ADR), + ("gap baseline", GAP_BASELINE), + ("test strategy", TEST_STRATEGY), + ("security", SECURITY), + ] { + assert!( + document.contains("verify_detached_artifact"), + "{name} does not document the current detached-artifact integrity boundary" + ); + } +} From 1e543bbcc343adad04b748109cdd2a22b0d49f1e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 18:52:04 +0900 Subject: [PATCH 51/67] docs(client): align detached artifact contract --- CHANGELOG.md | 7 ++++--- SECURITY.md | 7 +++++-- TEST_STRATEGY.md | 19 ++++++++++++------- docs/PRD.md | 2 +- docs/TRD.md | 16 +++++++++------- docs/UML.md | 15 ++++++++++----- .../0004-semantic-release-client-boundary.md | 8 ++++---- docs/product-technical-gap-baseline.md | 18 +++++++++--------- 8 files changed, 54 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 882a1d4c..7bd0bb7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,12 @@ All notable changes to ConceptWeave are documented here. - Draft 2020-12 JSON Schema for the semantic-candidate public contract. - Rust-first `conceptweave-client` supporting subdomain with deterministic offline semantic-release admission by contract version, publication state, truth status, provenance, stable concept identity, and declared SHA-256 digest identity. - Deterministic offline semantic-release diff that first applies the same authoritative-use admission policy, then reports stable previous/current release identity and sorted added/removed concept identifiers without network or model calls. -- Exact offline SHA-256 verification of caller-supplied serialized semantic-release bytes, with typed digest-mismatch evidence and the same fail-closed authoritative-use admission gate. +- Exact offline SHA-256 verification of caller-supplied detached immutable semantic-artifact bytes through `verify_detached_artifact`, with typed digest-mismatch evidence and the same fail-closed authoritative-use admission gate. - Explicit semantic-release compatibility policy that distinguishes the current contract version, caller-declared supported legacy versions, and unknown versions without inferring compatibility from version ordering; supported legacy releases still pass the same Published/Authoritative gate. - Explicit immutable semantic-release supersession references that bind predecessor and successor release ids to their exact artifact digests, require a rationale, reject self-supersession, and validate both releases through the ordinary authoritative-use gate without inferring replacement from version order or timestamps. - Draft 2020-12 `semantic-release` public JSON Schema with valid and fail-closed fixtures for non-authoritative publication, duplicate concept identifiers, and malformed digest identity. - Standards and research doctoring covering stable W3C ontology standards, 2026 RDF/SHACL work in progress, Apache Ossie, and recent LLM ontology-engineering/matching research. +- Executable documentation/API contract preventing the retired `verify_serialized_artifact` name or manifest-self-digest semantics from drifting back into Client Consumption documentation. ### Security @@ -24,7 +25,7 @@ All notable changes to ConceptWeave are documented here. - Client authoritative-use admission rejects incompatible, unpublished, or non-authoritative releases without requiring a network/model call. - Legacy compatibility is explicit opt-in policy; unknown versions remain fail-closed and the current version cannot also be configured as legacy. - Release diff validates both compared releases through the same fail-closed authoritative-use gate so comparison cannot bypass contract-version, publication-state, or truth-status policy. -- Serialized-artifact integrity verification first applies authoritative-use admission, then computes SHA-256 over the exact supplied bytes and rejects any mismatch with the declared release digest. -- Digest syntax validation remains distinct from byte verification so a syntactically valid digest is never treated as proof that serialized content matches it. +- Detached-artifact integrity verification first applies authoritative-use admission, then computes SHA-256 over the exact supplied detached semantic-artifact bytes and rejects any mismatch with the declared release digest. +- Digest syntax validation remains distinct from byte verification so a syntactically valid digest is never treated as proof that detached artifact content matches it. - Supersession validation requires exact predecessor/successor id-and-digest references and leaves the prior published release immutable; a correction is not inferred from ordering, timestamps, or semantic similarity. - Unsafe Rust is forbidden in the core domain and client crates. diff --git a/SECURITY.md b/SECURITY.md index f1a5ff7b..474d3d88 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,7 +16,9 @@ All source artifacts, generated candidate payloads, external ontology files, mod - reviewed authorization required before publication; - client authoritative-use admission must fail closed on unsupported contract versions, non-Published state, or non-Authoritative truth status; - client admission does not substitute for consuming-product tenant/purpose authorization; -- declared release digest syntax is not an integrity claim: exact serialized bytes must be hashed and compared before cryptographic integrity is asserted; +- declared release digest syntax is not an integrity claim: `SemanticReleaseClient::verify_detached_artifact` must hash the exact detached immutable semantic-artifact bytes and compare them with the declared digest before those supplied bytes are accepted as the referenced artifact; +- the release manifest's digest names detached artifact bytes rather than claiming a self-referential digest of the manifest bytes that contain that field; +- signature authenticity and provenance-chain verification remain separate controls until Governance & Publication defines a stable signing contract; - future tenant isolation applies to source snapshots, candidates, review receipts, releases, exports, and object storage; - published semantic truth is immutable: a published artifact must never be overwritten in place, including when an audit trail exists; corrections are issued as a new release that explicitly supersedes the prior release while retaining both releases and their provenance. @@ -34,6 +36,7 @@ All source artifacts, generated candidate payloads, external ontology files, mod 10. governance bypass from Proposed/Validated directly to Published; 11. in-place mutation or overwrite of previously published semantic truth; 12. consumer use of an incompatible, unpublished, non-authoritative, stale, or superseded release; -13. false integrity claims caused by checking digest syntax without hashing the exact artifact bytes. +13. false integrity claims caused by checking digest syntax without hashing the exact detached artifact bytes; +14. manifest/artifact scope confusion that validates bytes other than the semantic artifact named by the release digest. Security findings become tests before the related runtime capability can be marked release-ready. diff --git a/TEST_STRATEGY.md b/TEST_STRATEGY.md index ccbb8d43..d0382879 100644 --- a/TEST_STRATEGY.md +++ b/TEST_STRATEGY.md @@ -12,17 +12,22 @@ ## Current Client Consumption tests -- authoritative + Published release admits offline for the exact supported contract version; +- authoritative + Published release admits offline for the exact current or explicitly supported legacy contract version; - Reviewed/unpublished and Published/non-Authoritative releases fail closed; -- unsupported contract versions fail closed; +- unsupported contract versions fail closed without version-order inference; - release/contract/ontology identifiers reject blank values; - provenance is required; - concept identifiers reject blanks and duplicates; -- declared digest identity rejects unsupported algorithm, wrong length, and non-hex payloads; -- public error messages identify the rejected admission invariant; +- declared digest identity rejects unsupported algorithm, wrong length, uppercase and non-hex payloads; +- `SemanticReleaseClient::verify_detached_artifact` hashes exact detached immutable semantic-artifact bytes only after authoritative-use admission; +- exact bytes pass only when SHA-256 equals the declared artifact digest; changed/truncated/wrong bytes fail with typed mismatch evidence; +- release diff admits both releases and returns deterministic sorted concept changes; +- exact concept resolution is provider-independent and rejects blank identifiers; +- supersession validation binds distinct predecessor/successor release ids and digests, rejects self-supersession and blank rationale, and applies ordinary admission to both releases; +- public error messages identify the rejected admission/integrity/supersession invariant; - JSON Schema fixtures mirror Published -> Authoritative, unique concepts, provenance and digest-shape constraints. -Digest identity tests do not claim byte integrity. A future verifier must add golden exact-byte hashing plus one-byte mutation, truncation, serialization/canonicalization, wrong-digest and signature/provenance cases before integrity is release-ready. +Digest identity syntax and detached-byte integrity remain separate controls. The current verifier does not claim signature authenticity or provenance-chain trust. Those cases require a stable Governance & Publication signing contract before they become release gates. ## Future product test families @@ -36,7 +41,7 @@ Golden concept/type/taxonomy/relation sets; mapping precision/recall; multilingu ### Client compatibility and alignment -Current, older-supported, unsupported, malformed, partial, conflicting, stale and superseded releases; exact release diff; candidate-retrieval recall; OAEI-style matching precision/recall/F1; deterministic preprocessing ablations; abstention/ambiguity handling; LLM-call reduction against naive full-prompt baselines. Optional model calls use `contextual-orchestrator`; no model judge is sole truth. +Malformed, partial, conflicting, stale and superseded releases beyond the currently implemented explicit compatibility/diff/supersession contracts; candidate-retrieval recall; OAEI-style matching precision/recall/F1; deterministic preprocessing ablations; abstention/ambiguity handling; LLM-call reduction against naive full-prompt baselines. Optional model calls use `contextual-orchestrator`; no model judge is sole truth. ### Query-plan seam @@ -56,7 +61,7 @@ No bypass of Reviewed before Published, immutable published releases, rejection, ### Security -Prompt injection, malicious ontology/source/release content, SSRF, cross-tenant leakage, secret leakage, expression injection, resource exhaustion, replay, malformed source provenance, hostile export values, compatibility downgrade, stale/superseded use, and artifact tampering. +Prompt injection, malicious ontology/source/release content, SSRF, cross-tenant leakage, secret leakage, expression injection, resource exhaustion, replay, malformed source provenance, hostile export values, compatibility downgrade, stale/superseded use, and detached-artifact tampering. ### Evaluation diff --git a/docs/PRD.md b/docs/PRD.md index d199a757..05aacb06 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -60,7 +60,7 @@ A consuming product can inspect a versioned `semantic_release` offline and fail An admitted client can compare two releases deterministically without contacting a model/provider. Release diff applies the same authoritative-use admission policy to both inputs before returning stable previous/current release identity and sorted added/removed concept identifiers. Diff is semantic-contract evidence only; it does not authorize downstream data access, calculate business measures, mutate either release, or infer consuming-domain impact automatically. -The digest value object validates canonical `sha256:<64 lowercase hex>` identity syntax. Cryptographic integrity is a separate operation: `SemanticReleaseClient::verify_serialized_artifact` first applies authoritative-use admission, then hashes the exact caller-supplied detached artifact bytes and requires an exact digest match. Syntax validity alone is never integrity evidence. +The digest value object validates canonical `sha256:<64 lowercase hex>` identity syntax. Cryptographic integrity is a separate operation: `SemanticReleaseClient::verify_detached_artifact` first applies authoritative-use admission, then hashes the exact caller-supplied detached immutable semantic-artifact bytes and requires an exact digest match. The release manifest declares the artifact digest; it is not defined as a self-digest of the manifest bytes that carry that field. Syntax validity alone is never integrity evidence. A client can also validate an explicit immutable supersession declaration. `SemanticReleaseReference` binds a release id to its exact artifact digest. `ReleaseSupersession` names distinct predecessor/successor references plus a nonblank rationale, rejects self-supersession, and `validate_supersession` requires both releases to pass ordinary authoritative-use admission and both id+digest coordinates to match exactly. This is consumer-side validation only; it does not grant publication authority or infer supersession from version order, time, diff, or semantic similarity. A language-neutral supersession/publication-receipt schema remains required before cross-language client completeness is claimed. diff --git a/docs/TRD.md b/docs/TRD.md index d64a251f..5b22b931 100644 --- a/docs/TRD.md +++ b/docs/TRD.md @@ -10,7 +10,7 @@ ConceptWeave starts as a Rust-first modular monolith with explicit bounded conte 2. **Semantic Discovery** — evidence-bound candidate generation. 3. **Model Validation** — deterministic structural, ontology, constraint, and semantic-model validation. 4. **Governance & Publication** — review decisions, immutable releases, supersession. -5. **Client Consumption** — release admission, compatibility and future diff/match/resolve/query-plan contracts. +5. **Client Consumption** — release admission, compatibility, diff, exact resolution, detached-artifact integrity and supersession validation; later match/align/explain/query-plan contracts. 6. **Interoperability** — import/export adapters and CWL anti-corruption layers. The Core Domain is **Semantic Model Engineering**, represented by the discovery-to-publication lifecycle. Client Consumption is a supporting subdomain that protects downstream consumers from incompatible or non-governed releases. Identity, LLM routing, outbound web access, observability, catalog/search and consuming-product authorization are external/generic responsibilities. @@ -40,7 +40,7 @@ The initial Rust and JSON contracts cover candidate kind, truth status, publicat ## 6. Semantic-release client contract -The first Rust Client Consumption slice and Draft 2020-12 JSON Schema define an immutable consumer-visible contract containing: +The Rust Client Consumption slice and Draft 2020-12 JSON Schema define an immutable consumer-visible contract containing: - `release_id`; - `contract_version`; @@ -50,11 +50,13 @@ The first Rust Client Consumption slice and Draft 2020-12 JSON Schema define an - one or more provenance references; - unique stable concept identifiers. -`SemanticReleaseClient` supports deterministic offline admission for one explicit contract version. Authoritative use is rejected unless the release is both `Published` and `Authoritative`. Structural construction and client admission do not grant publication authority. +`SemanticReleaseClient` performs deterministic offline authoritative-use admission. A release is accepted only when its contract version is the explicit current version or one of the caller's explicit supported-legacy versions and its state is both `Published` and `Authoritative`. Compatibility is never inferred from version ordering. Structural construction and client admission do not grant publication authority. -`ReleaseDigest` currently validates only the declared `sha256:<64 hex>` identity syntax. A later integrity adapter must hash the exact serialized bytes and compare that digest before cryptographic integrity can be claimed. The serialized contract, compatibility rules and verifier remain versioned public boundaries. +`ReleaseDigest` validates canonical `sha256:<64 lowercase hex>` digest identity. `SemanticReleaseClient::verify_detached_artifact` then verifies cryptographic integrity of the exact detached immutable semantic-artifact bytes supplied by the caller, after applying the same authoritative-use admission gate. The release manifest declares the detached artifact digest; the digest is not specified as a self-referential hash of the manifest bytes containing that field. -Future #3 work adds older-supported compatibility policy, supersession/staleness handling, release diff, deterministic resolve, research-backed match/alignment, explain and query-plan operations. LLM-assisted client operations are optional; deterministic admission remains available with no provider call. +The current Client slice also provides deterministic release diff, exact concept resolution, and explicit immutable supersession validation. `ReleaseSupersession` binds predecessor and successor release ids to their exact artifact digests and never infers replacement from ordering, timestamps, semantic diff, or similarity. A language-neutral supersession/publication-receipt schema is still required before cross-language completeness is claimed. + +Remaining Issue #3 work includes signature/provenance-chain validation when Governance & Publication stabilizes a signing contract; relation/mapping/dimension/measure resolution; research-backed match/alignment/explanation; semantic query-plan contracts; GRC reference-client fixtures; and generated bindings after the language-neutral seam stabilizes. LLM-assisted client operations are optional and route only through `contextual-orchestrator`; admission, compatibility, diff, exact resolution, integrity and supersession validation remain deterministic and provider-independent. ## 7. LLM boundary @@ -70,8 +72,8 @@ No durable product database is claimed by the current slices. When persistence i ## 10. Security -Source artifacts and release payloads are untrusted input. Adapters must enforce source size/type bounds, parser timeouts, archive/decompression limits, SSRF-safe outbound access where external retrieval exists, and prompt-injection isolation for LLM-assisted extraction. Credentials and raw secrets never become semantic evidence. Client admission validates governance/compatibility but does not replace consuming-product tenant/purpose authorization. +Source artifacts and release payloads are untrusted input. Adapters must enforce source size/type bounds, parser timeouts, archive/decompression limits, SSRF-safe outbound access where external retrieval exists, and prompt-injection isolation for LLM-assisted extraction. Credentials and raw secrets never become semantic evidence. Client admission validates governance/compatibility but does not replace consuming-product tenant/purpose authorization. Exact detached artifact integrity must be verified against the declared digest before bytes are trusted as the referenced semantic artifact. ## 11. Evaluation -Evaluation must separate extraction recall, semantic correctness, structural correctness, ontology consistency, mapping accuracy, measure correctness, release compatibility/admission correctness, and governance outcomes. Model-judge scores may supplement but never replace deterministic golden fixtures and human-reviewed expert cases. Client matching later uses OAEI-style precision/recall/F1 and candidate-retrieval recall; release admission uses deterministic malformed/version/state/provenance/digest fixtures. +Evaluation must separate extraction recall, semantic correctness, structural correctness, ontology consistency, mapping accuracy, measure correctness, release compatibility/admission correctness, and governance outcomes. Model-judge scores may supplement but never replace deterministic golden fixtures and human-reviewed expert cases. Client matching later uses OAEI-style precision/recall/F1 and candidate-retrieval recall; release admission and integrity use deterministic malformed/version/state/provenance/digest/tamper fixtures. diff --git a/docs/UML.md b/docs/UML.md index 0f7d3423..4b4f1c96 100644 --- a/docs/UML.md +++ b/docs/UML.md @@ -38,13 +38,14 @@ sequenceDiagram Validator->>Steward: validated proposal Steward->>Publisher: reviewed acceptance Publisher-->>Source: no source mutation - Publisher-->>Client: immutable versioned semantic_release + Publisher-->>Client: immutable versioned semantic_release + detached artifact digest Client->>Client: validate contract version + Published + Authoritative + Client->>Client: verify_detached_artifact(exact bytes) Client-->>Consumer: admitted public release contract Consumer->>Consumer: tenant/purpose authorization + physical query planning/execution ``` -## Client admission decision +## Client admission and integrity decision ```mermaid flowchart TD @@ -54,8 +55,12 @@ flowchart TD P -- no --> X2[Reject: not published] P -- yes --> T{Truth status = Authoritative?} T -- no --> X3[Reject: not authoritative] - T -- yes --> A[Admit for downstream authorization] - A --> H[Future: hash exact serialized bytes and compare digest] + T -- yes --> A[Admit for deterministic client operations] + A --> H[verify_detached_artifact: hash exact detached bytes] + H --> M{Digest equals declared artifact digest?} + M -- no --> X4[Reject: artifact digest mismatch] + M -- yes --> C[Integrity evidence established for supplied artifact bytes] + C --> D[Consuming product performs tenant/purpose authorization] ``` -Client admission is not publication authority and is not downstream authorization. `ReleaseDigest` currently validates the declared digest identity syntax; the future hash step is required before cryptographic integrity is claimed. +Client admission is not publication authority and is not downstream authorization. `ReleaseDigest` validates canonical digest identity syntax; `SemanticReleaseClient::verify_detached_artifact` separately proves whether the exact detached artifact bytes supplied by the caller match that declared identity. diff --git a/docs/adr/0004-semantic-release-client-boundary.md b/docs/adr/0004-semantic-release-client-boundary.md index d575236c..db7850ba 100644 --- a/docs/adr/0004-semantic-release-client-boundary.md +++ b/docs/adr/0004-semantic-release-client-boundary.md @@ -19,7 +19,7 @@ Introduce **Client Consumption** as a Supporting Bounded Context and `conceptwea The current `semantic_release` public contract carries stable release identity, explicit contract and ontology/model versions, truth/publication state, a canonical declared artifact digest identity, provenance references, and unique stable concept identifiers. `SemanticReleaseClient` admits authoritative use only when the release uses the explicit current contract version or an explicitly configured supported-legacy version and is both `Published` and `Authoritative`. Compatibility is never inferred from semantic-version ordering. -`ReleaseDigest` accepts only canonical `sha256:<64 lowercase hex>` identity. `SemanticReleaseClient::verify_serialized_artifact` separately hashes the exact caller-supplied detached bytes and requires an exact digest match after authoritative-use admission. Digest syntax and byte-integrity evidence therefore remain distinct. +`ReleaseDigest` accepts only canonical `sha256:<64 lowercase hex>` identity. `SemanticReleaseClient::verify_detached_artifact` separately hashes the exact caller-supplied detached immutable semantic-artifact bytes and requires an exact digest match after authoritative-use admission. The manifest declares that detached artifact digest; the contract deliberately avoids a self-referential requirement to hash the manifest bytes containing the digest field. Digest syntax and byte-integrity evidence therefore remain distinct. `SemanticReleaseClient::diff` admits both releases through the same authoritative-use gate and reports deterministic sorted concept additions/removals. Exact concept resolution is deterministic and performs no fuzzy matching or model call. @@ -62,11 +62,11 @@ LLM-assisted future `match`, ambiguity explanation, and candidate ranking operat ## Verification evidence on the active branch -- Existing Rust integration tests cover authoritative admission, compatibility, non-Published/non-Authoritative states, provenance/identity requirements, duplicate concepts, digest syntax, exact byte verification, diff, and exact concept resolution. +- Existing Rust integration tests cover authoritative admission, compatibility, non-Published/non-Authoritative states, provenance/identity requirements, duplicate concepts, digest syntax, exact detached-byte verification, diff, and exact concept resolution. - Test-first supersession commit `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` introduced an API that did not yet exist and required immutable id+digest predecessor/successor references, rationale, self-supersession rejection, exact-reference validation, and ordinary authoritative admission. - Production commit `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements that bounded contract. Follow-up edge coverage binds mismatch checks to digest as well as id and exercises both predecessor and successor admission paths. -- Error-message coverage includes new supersession failures and reconciles the explicit compatibility wording. -- Hosted exact-head Product evidence is still required on the final unchanged documentation head; queued/predecessor results are not GREEN. +- Detached-artifact contract RED was observed on predecessor head `0c32a7b55d3c687ab76cee789962866573496ba1`: Product run `33664177838`, job `100361706615` acquired an Ubuntu 24.04 runner, verified the exact checkout, passed the CI contract/toolchain/fmt steps, then Clippy failed with `E0599` because `verify_detached_artifact` did not yet exist. Production head `9c278598001c502a733100d11e901538c3dc2677` applies only the causal API/rustdoc repair. +- Hosted exact-head GREEN is still required on the final unchanged documentation head; queued/predecessor results are not GREEN. ## Follow-up / acceptance for Accepted status diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 6351298a..bd961c11 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product / Technical Gap Baseline -**Snapshot:** 2026-09-02 +**Snapshot:** 2026-09-03 ## Shipped on protected `main` @@ -15,7 +15,7 @@ Only the repository bootstrap README exists before the foundation PR. No product | Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | | Quality gate | ConceptWeave | ACTIVE_PR | Exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` has Product run `33527150325` and SAST run `33527150417` terminal success. | | Security/test/operability | ConceptWeave + central `.github` | CONTROL_PLANE_BLOCKED | Security Scan run `33527150445` reached exact checkout; dependency-review job `100059571813` failed at `Check dependency review support`, so the pinned Dependency Review step was skipped. OSV/Trivy/Scorecard succeeded but are not substitutes. | -| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; fresh foundation threads are resolved but no qualifying APPROVED review exists. No self-approval or routine admin bypass is accepted. | +| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; fresh foundation threads are resolved but no qualifying independent human APPROVED review exists. No self-approval or routine admin bypass is accepted. | ## Active Client Consumption slice — PR #5 / Issue #3 @@ -25,26 +25,26 @@ PR #5 is intentionally stacked on PR #1 because the client reuses only the found | --- | --- | --- | --- | --- | --- | | Offline release admission | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `SemanticReleaseClient` requires explicit compatibility plus Published + Authoritative and remains provider/network independent. | Preserve downstream tenant/purpose authorization and physical execution boundaries. | Exact-head Rust tests/Clippy/docs/coverage. | | Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance and unique concept IDs. | Keep language-neutral contract stable before generated bindings. | Exact-head AJV + Rust contract parity. | -| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `verify_serialized_artifact` hashes exact caller-supplied bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. | Add signature/provenance-chain verification only when publication defines a stable signing contract. | Exact-head tamper/mutation fixtures and Product run. | +| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `verify_detached_artifact` hashes exact caller-supplied detached immutable semantic-artifact bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. Predecessor `0c32a7b55d3c687ab76cee789962866573496ba1` produced the expected hosted `E0599` RED when this API was absent; current production head `9c278598001c502a733100d11e901538c3dc2677` contains the minimal repair. | Keep the manifest digest scoped to detached artifact bytes; add signature/provenance-chain verification only when publication defines a stable signing contract. | Fresh exact-head Clippy/tests/rustdoc/coverage on the final documentation successor. | | Release diff | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Deterministic `diff` admits both releases through the same governance/compatibility gate and reports sorted added/removed concept IDs. | Extend only when typed relation/mapping/measure diff contracts exist. | Golden added/removed fixtures and exact-head Product run. | | Exact concept resolution | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `resolve_concept` performs exact deterministic lookup after authoritative-use admission; no fuzzy/LLM inference. | Add relation and physical-mapping resolution next. | Exact-head edge cases for unknown/blank IDs. | | Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first `091c36b24330671952de378d3596afcde5f62351`; production `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements Current / SupportedLegacy / Unsupported without version-order inference. | Keep support explicit and bounded; unknown versions remain fail closed. | Hosted exact-head Product/Clippy/tests on final unchanged head. | | Explicit immutable supersession | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | Test-first `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` required exact predecessor/successor id+digest references, nonblank rationale, self-supersession rejection, and ordinary authoritative-use admission. Production `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements `SemanticReleaseReference`, `ReleaseSupersession`, and `validate_supersession`; follow-up tests exercise digest mismatch and both predecessor/successor admission paths. | Add a language-neutral supersession/publication-receipt schema before cross-language completeness; do not infer replacement from version order/time/diff. ADR 0004 stays Proposed while PR #5 is Draft/checks incomplete. | Exact-head fmt/Clippy/tests/rustdoc/100% coverage plus public-contract parity. | +| Documentation/API parity | Client Consumption | REPAIRED_PENDING_CHECKS | Public Rust API is `verify_detached_artifact`; PRD/TRD/UML/ADR/TEST_STRATEGY/SECURITY and this baseline are aligned to detached-artifact semantics, with a Rust documentation contract preventing the retired `verify_serialized_artifact` name from returning. | Preserve manifest-vs-detached-artifact scope across future bindings and schemas. | Exact-head documentation contract + full Product gate. | | Match / align / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research traceability defines retrieve/filter/match constraints. | Deterministic candidate retrieval first; optional LLM only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | | Query-plan contract | Client Consumption | GAP | Issue #3 requires semantic plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | | Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution downstream. | Cross-tenant/purpose denial tests in each consumer. | ## Parallel Source Observation slice — PR #6 / Issue #2 -PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. At the latest live read in this commercialization iteration, PR #6 exact head `e56054cdce716a91759294b1993b31a1ca93ed57` preserves immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the new provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, and typed source-disappearance/resource-limit outcomes. Its exact-head Product run `33609118662` was queued before execution and therefore non-passing. A concrete Rust read-only PostgreSQL adapter remains open. +PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Fresh live evidence on 2026-09-03 identifies exact head `2817df62d0b7b41c0b0dd1bcbd34a444b8a5a092`. Its Product run `33696875090`, rust-quality job `100467545647`, remains queued before checkout on explicit `ubuntu-24.04`; queued evidence is non-passing. The branch retains immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, and typed source-disappearance/resource-limit outcomes. The current test-only lane tightens `observed_at_utc`; production validation must wait until that exact test head executes and demonstrates the intended RED. A concrete Rust read-only PostgreSQL adapter remains open. ## Central control-plane evidence -- `ContextualWisdomLab/.github#712` remains open and owns hosted-runner acquisition/queue health; queued jobs before checkout remain incomplete evidence. -- `ContextualWisdomLab/.github#810` remains open and confirms the central fail-open source defect is repaired while authoritative public non-fork Dependency Review availability/configuration is still unresolved. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. -- `ContextualWisdomLab/.github#772` remains open and owns the solo-maintainer approval-governance defect. Live ruleset `18156473` still has `required_approving_review_count: 1`, `required_reviewers: []`, thread resolution, required central workflows, deletion/non-fast-forward protection, and OrganizationAdmin bypass; self-approval/model-as-human/routine bypass are prohibited. -- `ContextualWisdomLab/.github#1219` remains open and owns stacked-PR central-review throughput. Leaf repositories must not duplicate the review scheduler. -- `.github` PR #1150 remains the open canonical read-only Actions queue-health evidence implementation; do not duplicate its collector. +- `ContextualWisdomLab/.github#712` remains the owner for hosted-runner acquisition/queue health; current PR #5 and PR #6 Product jobs are still queued before checkout on explicit `ubuntu-24.04`, so no-op source churn is not an acceptable retry mechanism. +- `ContextualWisdomLab/.github#810` owns authoritative public non-fork Dependency Review availability/configuration. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. +- `ContextualWisdomLab/.github#772` owns the solo-maintainer approval-governance defect. ConceptWeave does not self-approve or count model/bot reviews as an independent human approval. +- Central required-workflow/runtime repairs are evidence only after protected integration and unchanged ConceptWeave-head revalidation; predecessor runs do not transfer. ## Remaining P0 product gaps From fa0e31272097d154427ac53bfb7cc60dc96e72c8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 07:44:09 +0900 Subject: [PATCH 52/67] fix(client): remove retired API name from gap baseline --- 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 bd961c11..cb801861 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -30,7 +30,7 @@ PR #5 is intentionally stacked on PR #1 because the client reuses only the found | Exact concept resolution | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `resolve_concept` performs exact deterministic lookup after authoritative-use admission; no fuzzy/LLM inference. | Add relation and physical-mapping resolution next. | Exact-head edge cases for unknown/blank IDs. | | Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first `091c36b24330671952de378d3596afcde5f62351`; production `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements Current / SupportedLegacy / Unsupported without version-order inference. | Keep support explicit and bounded; unknown versions remain fail closed. | Hosted exact-head Product/Clippy/tests on final unchanged head. | | Explicit immutable supersession | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | Test-first `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` required exact predecessor/successor id+digest references, nonblank rationale, self-supersession rejection, and ordinary authoritative-use admission. Production `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements `SemanticReleaseReference`, `ReleaseSupersession`, and `validate_supersession`; follow-up tests exercise digest mismatch and both predecessor/successor admission paths. | Add a language-neutral supersession/publication-receipt schema before cross-language completeness; do not infer replacement from version order/time/diff. ADR 0004 stays Proposed while PR #5 is Draft/checks incomplete. | Exact-head fmt/Clippy/tests/rustdoc/100% coverage plus public-contract parity. | -| Documentation/API parity | Client Consumption | REPAIRED_PENDING_CHECKS | Public Rust API is `verify_detached_artifact`; PRD/TRD/UML/ADR/TEST_STRATEGY/SECURITY and this baseline are aligned to detached-artifact semantics, with a Rust documentation contract preventing the retired `verify_serialized_artifact` name from returning. | Preserve manifest-vs-detached-artifact scope across future bindings and schemas. | Exact-head documentation contract + full Product gate. | +| Documentation/API parity | Client Consumption | REPAIRED_PENDING_CHECKS | Public Rust API is `verify_detached_artifact`; PRD/TRD/UML/ADR/TEST_STRATEGY/SECURITY and this baseline are aligned to detached-artifact semantics, with a Rust documentation contract preventing the retired serialized-artifact API name from returning. | Preserve manifest-vs-detached-artifact scope across future bindings and schemas. | Exact-head documentation contract + full Product gate. | | Match / align / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research traceability defines retrieve/filter/match constraints. | Deterministic candidate retrieval first; optional LLM only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | | Query-plan contract | Client Consumption | GAP | Issue #3 requires semantic plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | | Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution downstream. | Cross-tenant/purpose denial tests in each consumer. | From cd99eb4a42011206f8efa376106aa4b121d2010e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 09:44:05 +0900 Subject: [PATCH 53/67] docs: refresh live Source Observation gap evidence --- docs/product-technical-gap-baseline.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index cb801861..77f7a595 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product / Technical Gap Baseline -**Snapshot:** 2026-09-03 +**Snapshot:** 2026-09-04 ## Shipped on protected `main` @@ -37,7 +37,9 @@ PR #5 is intentionally stacked on PR #1 because the client reuses only the found ## Parallel Source Observation slice — PR #6 / Issue #2 -PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Fresh live evidence on 2026-09-03 identifies exact head `2817df62d0b7b41c0b0dd1bcbd34a444b8a5a092`. Its Product run `33696875090`, rust-quality job `100467545647`, remains queued before checkout on explicit `ubuntu-24.04`; queued evidence is non-passing. The branch retains immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, and typed source-disappearance/resource-limit outcomes. The current test-only lane tightens `observed_at_utc`; production validation must wait until that exact test head executes and demonstrates the intended RED. A concrete Rust read-only PostgreSQL adapter remains open. +PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Fresh live evidence on 2026-09-04 identifies test-only exact head `c9af2255fb721b8e05e608e6b2525017b1f59151`. Its Product run `33760465773`, rust-quality job `100665220457`, remains queued before runner assignment on explicit `ubuntu-24.04` with `runner_id=0` and `steps=[]`; queued evidence is non-passing. The branch retains immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, typed source-disappearance/resource-limit outcomes, and opaque bounded source registry keys. + +The prior UTC-provenance RED executed on predecessor `2817df62d0b7b41c0b0dd1bcbd34a444b8a5a092`: Product `33696875090`, job `100467545647`, passed exact checkout/CI/Rust/fmt/Clippy and failed because malformed `observed_at_utc="time"` was accepted. Production `e27ffaf4a40d746781b8012e9fe71467e7e6511f` repaired that boundary with deterministic explicit-UTC validation. The current test-only lane instead covers a separate invariant: public `PostgresSchemaSnapshot::new` must enforce the same opaque ≤128-byte lowercase multiword `snake_case` registry-key boundary as `ObservationRequest`, so DSN/credential-shaped or malformed identities cannot be copied into immutable `source_id` provenance. Production remains intentionally unchanged until exact head `c9af2255...` executes the intended RED. A concrete Rust read-only PostgreSQL adapter remains open after that RED -> minimal fix -> exact-head GREEN sequence. ## Central control-plane evidence @@ -48,7 +50,7 @@ PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Fresh live evi ## Remaining P0 product gaps -1. **Source Observation adapter** — implement the new bounded source port with a real Rust read-only PostgreSQL adapter, immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen anonymized GRC fixture. +1. **Source Observation adapter** — after the current registry-identity RED -> minimal production repair -> exact-head GREEN, implement a concrete Rust read-only PostgreSQL adapter behind the existing bounded source port with immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen anonymized GRC fixture. 2. **Observation-to-candidate provenance** — exact source receipt plus discovery method/proposal receipt for every generated candidate. 3. **Ontology induction** — deterministic observations plus `contextual-orchestrator` structured candidate generation for concepts, taxonomy and non-taxonomic relations. 4. **Semantic-layer induction** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts. From 3f77af6810f5b7a10a7f66e9afafa9ebb337f0f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 12:59:45 +0900 Subject: [PATCH 54/67] docs(client): adopt current foundation gap authority --- docs/product-technical-gap-baseline.md | 108 +++++++++++-------------- 1 file changed, 47 insertions(+), 61 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 77f7a595..6fcba59c 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -2,76 +2,62 @@ **Snapshot:** 2026-09-04 -## Shipped on protected `main` +This branch is the Client Consumption child of Foundation PR #1. Exact PR/run coordinates are evidence snapshots, never mutable production dependencies. Protected/live GitHub state is authoritative when it advances after this snapshot. -Only the repository bootstrap README exists before the foundation PR. No production capability is claimed from protected `main` yet. +## Stack authority -## Active foundation slice — PR #1 +- Protected/default `main`: `f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425`; no ConceptWeave release exists. +- Foundation PR #1 advanced by documentation-only live-state repair from `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` to `447aa0723abd7b582b9acc478ed90238d0d59214`. The delta between those heads is only this gap-baseline file. Current Foundation Product `33835025486`, job `100905656541`, is queued before runner assignment; predecessor Product/SAST success and Security failure remain historical evidence only. +- Client PR #5 pre-restack head `cd99eb4a42011206f8efa376106aa4b121d2010e` is Draft. Product `33822984126`, job `100869494950`, remains queued before runner assignment and is superseded for acceptance by this Foundation-adoption restack. +- Source Observation PR #6 pre-restack head is `1fdfb3af14c126c270861eb541e9e57d47418bb8`; Product `33834639272`, job `100904527699`, remains queued before runner assignment. Its production registry-key validation is intentionally unchanged pending the real semantic RED. -| Area | Owner | Status | Evidence / action / next verification | +## Client Consumption capability status + +| Gap | Status | Evidence / invariant | Next verification | | --- | --- | --- | --- | -| Product boundary | ConceptWeave | ACTIVE_PR | PRD/TRD/ADR/context map define Semantic Model Engineering and CWL boundaries. Revalidate against exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` before merge. | -| Truth/publication lifecycle | Governance & Publication | ACTIVE_PR | Rust domain lifecycle defines Draft -> Proposed -> Validated while public transition APIs fail closed at steward-reviewed/publication boundaries; Draft 2020-12 candidate schema enforces public candidate shape and Published -> Authoritative consistency. | -| Rust baseline | ConceptWeave | ACTIVE_PR | Rust 1.98.0 workspace, unsafe forbidden, public docs required. | -| Quality gate | ConceptWeave | ACTIVE_PR | Exact PR #1 head `bba351b77bf5f1ab5cfd55979fbb2bd158f78b81` has Product run `33527150325` and SAST run `33527150417` terminal success. | -| Security/test/operability | ConceptWeave + central `.github` | CONTROL_PLANE_BLOCKED | Security Scan run `33527150445` reached exact checkout; dependency-review job `100059571813` failed at `Check dependency review support`, so the pinned Dependency Review step was skipped. OSV/Trivy/Scorecard succeeded but are not substitutes. | -| Merge governance | ContextualWisdomLab/.github | CONTROL_PLANE_BLOCKED | Live organization ruleset `18156473` requires one approving review and thread resolution on `~DEFAULT_BRANCH`; fresh foundation threads are resolved but no qualifying independent human APPROVED review exists. No self-approval or routine admin bypass is accepted. | +| Offline release admission | IMPLEMENTED_PENDING_CURRENT_HEAD | `SemanticReleaseClient` requires explicit compatibility plus Published + Authoritative and remains provider/network independent. Downstream tenant/purpose authorization and physical execution remain downstream. | Exact-head Rust tests/Clippy/rustdoc/coverage after restack. | +| Versioned semantic release | IMPLEMENTED_PENDING_CURRENT_HEAD | `contracts/semantic-release.schema.json` plus fixtures and Rust `SemanticRelease` carry release/contract/ontology identity, truth/publication state, digest identity, provenance and unique concept IDs. | Draft-2020-12 schema and Rust parity. | +| Detached artifact integrity | REPAIRED_PENDING_CURRENT_HEAD | Predecessor `0c32a7b55d3c687ab76cee789962866573496ba1` produced hosted `E0599` because tests required `verify_detached_artifact` while production exposed the retired API. `9c278598001c502a733100d11e901538c3dc2677` made the minimal API/rustdoc repair. | Exact-head Clippy/tests/rustdoc/coverage. | +| Public documentation parity | REPAIRED_PENDING_CURRENT_HEAD | Product `33741224641`, job `100603361888`, executed exact `1e543bb...`, passed CI/fmt/Clippy and failed the documentation contract because the gap baseline itself reproduced the retired identifier. `fa0e31272097d154427ac53bfb7cc60dc96e72c8` removed that self-reference; `cd99eb4...` then repaired stale sibling Source Observation state. | Current restacked Product gate. | +| Explicit compatibility | IMPLEMENTED_PENDING_CURRENT_HEAD | Current / SupportedLegacy / Unsupported are explicit; unknown versions fail closed and no ordering inference is used. | Unknown/legacy/current edge cases. | +| Deterministic diff / resolution | IMPLEMENTED_PENDING_CURRENT_HEAD | Release diff reports deterministic sorted concept changes; exact concept resolution has no fuzzy/model behavior. | Golden diff and unknown/blank resolution cases. | +| Immutable supersession validation | IMPLEMENTED_PENDING_CURRENT_HEAD | `SemanticReleaseReference`, `ReleaseSupersession` and `validate_supersession` bind exact predecessor/successor IDs and digests, nonblank rationale, no self-supersession and authoritative-use admission. Authority to issue a governed supersession receipt remains Governance & Publication. | Exact-head tests plus public cross-language contract. | +| Language-neutral supersession/publication contract | INTENTIONAL_RED_PENDING | Test-first lineage beginning `143506eb66b6904b770a628ac793af2253559df2` requires `contracts/semantic-release-supersession.schema.json` and valid/invalid fixtures. Production artifacts remain intentionally absent. | Observe the missing-schema/fixture RED only after the restacked head reaches that public-contract boundary, then make the smallest generic repair. | +| Match / align / explain | GAP | OLaLA/LLMs4OM/Complex Matching/MILA/KROMA/LLM4VKG research is mapped to retrieve/filter/match and evaluation. LLM output is proposed only and any production call must use released `contextual-orchestrator`. | OAEI-style P/R/F1, retrieval recall, abstention, reproducibility and LLM-call reduction. | +| Query-plan contract | GAP | ConceptWeave may define semantic plans but cannot own downstream physical authorization/execution. | Versioned DTO + GRC round-trip without cross-service SQL. | -## Active Client Consumption slice — PR #5 / Issue #3 +## Sibling Source Observation state -PR #5 is intentionally stacked on PR #1 because the client reuses only the foundation's public evidence/truth/publication types. It remains Draft. The canonical exact head is the live GitHub PR head; editing this file changes that SHA, so check evidence is valid only for the later unchanged branch head. +The Source Observation bounded context already contains immutable PostgreSQL table/column/PK/unique/FK/CHECK evidence, exact identifier preservation, canonical lowercase SHA-256 snapshot identity, UTC provenance, typed exact receipts, explicit resource budgets/cancellation/failures and an opaque bounded source registry key at the port boundary. -| Gap | Owner | Status | Evidence | Action | Next verification | -| --- | --- | --- | --- | --- | --- | -| Offline release admission | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `SemanticReleaseClient` requires explicit compatibility plus Published + Authoritative and remains provider/network independent. | Preserve downstream tenant/purpose authorization and physical execution boundaries. | Exact-head Rust tests/Clippy/docs/coverage. | -| Versioned semantic-release shape | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | `contracts/semantic-release.schema.json` + fixtures; Rust `SemanticRelease` carries release/contract/ontology identity, truth/publication state, digest identity, provenance and unique concept IDs. | Keep language-neutral contract stable before generated bindings. | Exact-head AJV + Rust contract parity. | -| Detached artifact integrity | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `verify_detached_artifact` hashes exact caller-supplied detached immutable semantic-artifact bytes with SHA-256 and compares the canonical declared digest after authoritative-use admission. Predecessor `0c32a7b55d3c687ab76cee789962866573496ba1` produced the expected hosted `E0599` RED when this API was absent; current production head `9c278598001c502a733100d11e901538c3dc2677` contains the minimal repair. | Keep the manifest digest scoped to detached artifact bytes; add signature/provenance-chain verification only when publication defines a stable signing contract. | Fresh exact-head Clippy/tests/rustdoc/coverage on the final documentation successor. | -| Release diff | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Deterministic `diff` admits both releases through the same governance/compatibility gate and reports sorted added/removed concept IDs. | Extend only when typed relation/mapping/measure diff contracts exist. | Golden added/removed fixtures and exact-head Product run. | -| Exact concept resolution | Client Consumption | IMPLEMENTED_PENDING_CHECKS | `resolve_concept` performs exact deterministic lookup after authoritative-use admission; no fuzzy/LLM inference. | Add relation and physical-mapping resolution next. | Exact-head edge cases for unknown/blank IDs. | -| Explicit legacy compatibility | Client Consumption | IMPLEMENTED_PENDING_CHECKS | Test-first `091c36b24330671952de378d3596afcde5f62351`; production `2a4596e88d016e01a3bffded7a8436b14d55ec18` implements Current / SupportedLegacy / Unsupported without version-order inference. | Keep support explicit and bounded; unknown versions remain fail closed. | Hosted exact-head Product/Clippy/tests on final unchanged head. | -| Explicit immutable supersession | Client Consumption / Governance & Publication seam | IMPLEMENTED_PENDING_CHECKS | Test-first `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` required exact predecessor/successor id+digest references, nonblank rationale, self-supersession rejection, and ordinary authoritative-use admission. Production `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements `SemanticReleaseReference`, `ReleaseSupersession`, and `validate_supersession`; follow-up tests exercise digest mismatch and both predecessor/successor admission paths. | Add a language-neutral supersession/publication-receipt schema before cross-language completeness; do not infer replacement from version order/time/diff. ADR 0004 stays Proposed while PR #5 is Draft/checks incomplete. | Exact-head fmt/Clippy/tests/rustdoc/100% coverage plus public-contract parity. | -| Documentation/API parity | Client Consumption | REPAIRED_PENDING_CHECKS | Public Rust API is `verify_detached_artifact`; PRD/TRD/UML/ADR/TEST_STRATEGY/SECURITY and this baseline are aligned to detached-artifact semantics, with a Rust documentation contract preventing the retired serialized-artifact API name from returning. | Preserve manifest-vs-detached-artifact scope across future bindings and schemas. | Exact-head documentation contract + full Product gate. | -| Match / align / explain | Model Alignment + Client Consumption | GAP | OLaLa/LLMs4OM/MILA/KROMA research traceability defines retrieve/filter/match constraints. | Deterministic candidate retrieval first; optional LLM only through `contextual-orchestrator`; never auto-authorize correspondences. | OAEI-style P/R/F1, retrieval recall, abstention and LLM-call-reduction evidence. | -| Query-plan contract | Client Consumption | GAP | Issue #3 requires semantic plans without owning physical execution. | Define versioned semantic query-plan DTO and consuming-product ACL seam. | GRC golden round-trip with no cross-service SQL. | -| Consumer authorization | Downstream product / Keyverse boundary | EXTERNAL_OWNERSHIP | ConceptWeave performs governance/compatibility admission only. | Keep tenant/purpose authorization and physical execution downstream. | Cross-tenant/purpose denial tests in each consumer. | +The prior UTC RED executed on `2817df62...` and was repaired by `e27ffaf4a40d746781b8012e9fe71467e7e6511f`. A later cross-boundary test on `c9af2255...` requires `PostgresSchemaSnapshot::new` to enforce the same ≤128-byte lowercase multiword `snake_case` registry identity as `ObservationRequest`; its hosted run first failed at formatting before reaching the semantic test. Test formatting was repaired, an accidental whole-file write was neutralized by a non-force forward commit whose tree compared exactly equal to the intended predecessor, and `1fdfb3af...` now contains only the remaining rustfmt wrapping hunk. The semantic production validator still must not land before the real RED. -## Parallel Source Observation slice — PR #6 / Issue #2 +After registry RED → minimal fix → exact-head GREEN, the next Source Observation buyer slice is a maintained Rust read-only PostgreSQL adapter behind `conceptweave-source-port`, with adapter-local credential resolution, explicit schema allowlist, statement timeout, cancellation, row/byte/concurrency budgets, complete-or-fail snapshot construction and a frozen anonymized GRC-shaped replay fixture. -PR #6 is a sibling stacked on PR #1 and is not copied into PR #5. Fresh live evidence on 2026-09-04 identifies test-only exact head `c9af2255fb721b8e05e608e6b2525017b1f59151`. Its Product run `33760465773`, rust-quality job `100665220457`, remains queued before runner assignment on explicit `ubuntu-24.04` with `runner_id=0` and `steps=[]`; queued evidence is non-passing. The branch retains immutable PostgreSQL snapshot/source receipts, PK/unique/FK/CHECK evidence, FK reference behavior, PostgreSQL 18 FK validation/enforcement state, and the provider-independent `conceptweave-source-port` with explicit statement-timeout/row/byte/concurrency bounds, exact non-empty schema allowlists, caller cancellation, typed source-disappearance/resource-limit outcomes, and opaque bounded source registry keys. +## Central control-plane evidence -The prior UTC-provenance RED executed on predecessor `2817df62d0b7b41c0b0dd1bcbd34a444b8a5a092`: Product `33696875090`, job `100467545647`, passed exact checkout/CI/Rust/fmt/Clippy and failed because malformed `observed_at_utc="time"` was accepted. Production `e27ffaf4a40d746781b8012e9fe71467e7e6511f` repaired that boundary with deterministic explicit-UTC validation. The current test-only lane instead covers a separate invariant: public `PostgresSchemaSnapshot::new` must enforce the same opaque ≤128-byte lowercase multiword `snake_case` registry-key boundary as `ObservationRequest`, so DSN/credential-shaped or malformed identities cannot be copied into immutable `source_id` provenance. Production remains intentionally unchanged until exact head `c9af2255...` executes the intended RED. A concrete Rust read-only PostgreSQL adapter remains open after that RED -> minimal fix -> exact-head GREEN sequence. +Protected central source is `.github/main@07d9ec23fb265c76539d23249e1dfa124ea7b23b` at this snapshot; this is evidence, not a ConceptWeave dependency. -## Central control-plane evidence +- `.github#810` owns authoritative Dependency Review availability. OSV/Trivy/Scorecard/SAST are not substitutes and 403 cannot be treated as success. +- `.github#712/#1531` own selective/intermittent runner admission and review/queue amplification. +- `.github#1796` has test-first Draft #1821 `test/1796-org-sweep-queue-owner@9c79cf775ad6a125a94dedcae9683c20a65a0339`, which separates organization-sweep queue inventory from target-repository exact-head coalescing. Production central source remains unchanged until its RED executes. +- `.github#1822@7a5cc1b1c43946d210405cd051ae629ff2c44966` is a separate Draft fix for documented `CoalescingRefused` safe-no-op behavior; other exceptions remain fail closed. +- Fresh central queued inventory reached 1,906 runs. Aggregate backlog movement is diagnostic only; acceptance still requires actual runner assignment, exact checkout and terminal evidence on unchanged current heads. + +## Remaining P0 gaps + +1. Observe and repair the language-neutral supersession/publication contract RED, then prove exact-head GREEN. +2. Complete signature/provenance verification after Governance & Publication defines a stable signing contract. +3. Add relation, physical-mapping, dimension and measure resolution plus a versioned semantic query-plan contract. +4. Complete deterministic/research-backed match, alignment and explanation with optional bounded contextual-orchestrator assistance only. +5. Add GRC reference fixtures that exercise only released/versioned `semantic_release` contracts while GRC retains business truth, tenant/purpose authorization and physical execution. +6. Complete ontology/semantic-layer discovery, validation, governance persistence, steward review, publication adapters, multilingual evaluation, observability/recovery and immutable release evidence in their owning bounded contexts. + +## DDD and release invariants -- `ContextualWisdomLab/.github#712` remains the owner for hosted-runner acquisition/queue health; current PR #5 and PR #6 Product jobs are still queued before checkout on explicit `ubuntu-24.04`, so no-op source churn is not an acceptable retry mechanism. -- `ContextualWisdomLab/.github#810` owns authoritative public non-fork Dependency Review availability/configuration. ConceptWeave must not substitute OSV/Trivy/Scorecard or fail open. -- `ContextualWisdomLab/.github#772` owns the solo-maintainer approval-governance defect. ConceptWeave does not self-approve or count model/bot reviews as an independent human approval. -- Central required-workflow/runtime repairs are evidence only after protected integration and unchanged ConceptWeave-head revalidation; predecessor runs do not transfer. - -## Remaining P0 product gaps - -1. **Source Observation adapter** — after the current registry-identity RED -> minimal production repair -> exact-head GREEN, implement a concrete Rust read-only PostgreSQL adapter behind the existing bounded source port with immutable receipts, domains/enums/indexes/comments, hostile-input/resource bounds, cancellation/source-disappearance behavior, and a frozen anonymized GRC fixture. -2. **Observation-to-candidate provenance** — exact source receipt plus discovery method/proposal receipt for every generated candidate. -3. **Ontology induction** — deterministic observations plus `contextual-orchestrator` structured candidate generation for concepts, taxonomy and non-taxonomic relations. -4. **Semantic-layer induction** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts. -5. **Validation engine** — RDF/OWL/SKOS/SHACL publication validation, consistency checks, duplicate/conflict detection and bounded reasoning. -6. **Governance persistence** — PostgreSQL 3NF candidates, evidence, validation receipts, review decisions, immutable releases, explicit supersession/publication receipts, transactional outbox and temporal history where warranted. -7. **Review workflow** — Keyverse tenant/role/purpose context, steward review, maker-checker where required, stale-decision protection and immutable publication receipt. -8. **Publication adapters** — OWL/RDFS/SKOS/SHACL/JSON-LD and version-bound Apache Ossie export. -9. **Client completion** — language-neutral supersession/publication receipt, relation/mapping/dimension/measure resolution, signature/provenance contract, research-backed match/align/explain, semantic query-plan API, and GRC reference fixtures. -10. **CWL integration** — `semantic-data-portal`, `LineageWeave`, `context-graph-contracts`, GRC and EA through published contracts only. -11. **Evaluation harness** — ontology-learning/matching golden fixtures, structural/semantic metrics, human-reviewed cases, replay reproducibility and multilingual cases. -12. **Observability/release** — shared OpenTelemetry bootstrap, structured security events, SBOM/provenance/signing, backup/restore and protected release evidence. - -## DDD fitness gaps and invariants - -- No generic `utils/helpers/services/common` domain buckets are permitted. -- Adapters remain outside owned domain/client/source-observation contracts. -- Client Consumption consumes versioned public release contracts only, never generator-private implementation or persistence. -- Supersession validation is a Client Consumption contract; authority to issue the governed supersession/publication receipt remains Governance & Publication. -- Published releases are immutable; correction creates a distinct successor and preserves the predecessor. -- Source Observation preserves source evidence but does not infer semantic authority. -- Foreign product DTOs require Anti-Corruption Layers. -- `semantic-data-portal` remains catalog/governance/consumption plane, not ConceptWeave persistence. -- Consuming-product authorization/query execution stays downstream; ConceptWeave does not own foreign application tables. -- Future persistence uses descriptive two-or-more-word `snake_case` objects, 3NF by default, explicit item-level UPSERT/idempotency and immutable published releases. +- No generic `utils/helpers/services/common` domain buckets. +- Client Consumption depends only on governed public release contracts, never generator-private classes, prompts, persistence tables or orchestration state. +- `semantic-data-portal` remains catalog/governance/consumption; `context-graph-contracts` owns interop contracts; `enterprise-architecture-core` owns EA; `contextual-orchestrator` owns provider routing. +- No source copying, cross-service SQL or mutable foreign-head dependency. +- Published semantic truth is immutable; correction creates a distinct successor plus supersession evidence. +- Release requires exact protected head, version/CHANGELOG/tag/package/immutable `semantic_release`, SBOM, provenance, reproducibility and rollback evidence. From 30fdde3746f023a2fab010bcb0b46e670ded0b6e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 13:20:15 +0900 Subject: [PATCH 55/67] chore: adopt foundation doctoring RED --- .../tests/research_reference_traceability.rs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 crates/conceptweave-domain/tests/research_reference_traceability.rs diff --git a/crates/conceptweave-domain/tests/research_reference_traceability.rs b/crates/conceptweave-domain/tests/research_reference_traceability.rs new file mode 100644 index 00000000..41d9b3b6 --- /dev/null +++ b/crates/conceptweave-domain/tests/research_reference_traceability.rs @@ -0,0 +1,26 @@ +const REFERENCES: &str = include_str!("../../../docs/doctoring/REFERENCES.md"); +const TRACEABILITY: &str = + include_str!("../../../docs/doctoring/RESEARCH_CAPABILITY_TRACEABILITY.md"); + +#[test] +fn adopted_alignment_studies_have_authoritative_bibliography_records() { + for (traceability_marker, authoritative_record) in [ + ( + "He, Chen, Dong, & Horrocks (2023)", + "https://ceur-ws.org/Vol-3632/ISWC2023_paper_427.pdf", + ), + ( + "Amini, Saki Norouzi, Hitzler, & Amini (2024)", + "https://doi.org/10.1007/978-3-031-81221-7_2", + ), + ] { + assert!( + TRACEABILITY.contains(traceability_marker), + "an adopted study must remain explicit in research-to-capability traceability: {traceability_marker}" + ); + assert!( + REFERENCES.contains(authoritative_record), + "an adopted study must have an authoritative publication record in the APA bibliography: {authoritative_record}" + ); + } +} From 4a771af962306febb4318aed4de48254d96f32f9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 21:08:37 +0900 Subject: [PATCH 56/67] fix(ci): preserve client contract checks after restack --- .github/workflows/product.yml | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index b14f5465..bef62411 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -61,7 +61,7 @@ jobs: - name: Exact owned coverage run: ./scripts/check_coverage.sh - - name: Validate public JSON contract + - name: Validate public JSON contracts run: | npx --yes ajv-cli@5.0.0 compile \ --spec=draft2020 \ @@ -86,12 +86,62 @@ jobs: -s contracts/semantic-candidate.schema.json \ -d contracts/fixtures/semantic-candidate.invalid-state-truth-mismatch.json \ --invalid + npx --yes ajv-cli@5.0.0 compile \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.valid.json \ + --valid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-published-truth.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-duplicate-concept.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-digest.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release.schema.json \ + -d contracts/fixtures/semantic-release.invalid-uppercase-digest.json \ + --invalid + npx --yes ajv-cli@5.0.0 compile \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.valid.json \ + --valid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.invalid-digest.json \ + --invalid + npx --yes ajv-cli@5.0.0 test \ + --spec=draft2020 \ + -s contracts/semantic-release-supersession.schema.json \ + -d contracts/fixtures/semantic-release-supersession.invalid-rationale.json \ + --invalid - name: Lockfile freshness run: | cargo generate-lockfile --locked git ls-files --error-unmatch Cargo.lock >/dev/null - test -z "$(git status --porcelain=v1 --untracked-files=all -- Cargo.lock)" + if ! test -z "$(git status --porcelain=v1 --untracked-files=all -- Cargo.lock)"; then + echo "::error::Cargo.lock changed while validating the declared dependency graph" + git diff -- Cargo.lock + exit 1 + fi - name: Clean working tree run: test -z "$(git status --porcelain=v1 --untracked-files=all)" From 61776fbf5969ec4f8897f48b7bd410052f83ea9d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 21:26:03 +0900 Subject: [PATCH 57/67] fix(client): repair stacked integration gates Reserve ADR 0004 for Source Observation and move the Client boundary to ADR 0005. Deduplicate LLVM source regions across integration-test binaries and restore the documented detached-artifact contract. Signed-off-by: Seongho Bae --- ARCHITECTURE.md | 2 +- crates/conceptweave-client/src/lib.rs | 11 ++--- .../tests/digest_canonicalization.rs | 2 +- .../tests/documentation_contract.rs | 6 +-- .../tests/release_compatibility.rs | 8 +++ .../tests/release_supersession.rs | 2 +- ... 0005-semantic-release-client-boundary.md} | 2 +- docs/adr/README.md | 2 +- docs/product-technical-gap-baseline.md | 2 +- scripts/check_coverage.sh | 49 +++++++++++++++++-- 10 files changed, 67 insertions(+), 19 deletions(-) rename docs/adr/{0004-semantic-release-client-boundary.md => 0005-semantic-release-client-boundary.md} (99%) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 89e0f073..18f7b009 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -99,4 +99,4 @@ scripts/ # Deterministic repository-quality helpers Adapters and application services are added only when their bounded responsibility exists; generic `utils`, `helpers`, or `services` dumping grounds are prohibited. -ADR 0004 remains Proposed while PR #5 is Draft and current-head checks/governance are incomplete; implementation on an unintegrated head is not sufficient to mark the architecture decision Accepted. +ADR 0005 remains Proposed while PR #5 is Draft and current-head checks/governance are incomplete; implementation on an unintegrated head is not sufficient to mark the architecture decision Accepted. diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index f852d319..086251bd 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -23,8 +23,7 @@ pub struct ReleaseDigest(String); impl ReleaseDigest { /// Parses a release digest and rejects unsupported algorithms or malformed hex. - pub fn new(value: impl Into) -> Result { - let value = value.into(); + pub fn new(value: &str) -> Result { let Some(hex) = value.strip_prefix("sha256:") else { return Err(ReleaseContractError::InvalidDigest); }; @@ -37,7 +36,7 @@ impl ReleaseDigest { { return Err(ReleaseContractError::InvalidDigest); } - Ok(Self(value)) + Ok(Self(value.to_owned())) } /// Returns the canonical digest identity string. @@ -368,10 +367,8 @@ impl SemanticReleaseClient { } /// Returns explicitly supported legacy contract versions in deterministic order. - pub fn supported_legacy_contract_versions(&self) -> impl Iterator { - self.supported_legacy_contract_versions - .iter() - .map(String::as_str) + pub fn supported_legacy_contract_versions(&self) -> &BTreeSet { + &self.supported_legacy_contract_versions } /// Classifies a release against the client's explicit compatibility policy. diff --git a/crates/conceptweave-client/tests/digest_canonicalization.rs b/crates/conceptweave-client/tests/digest_canonicalization.rs index 449268ba..99cdc7bf 100644 --- a/crates/conceptweave-client/tests/digest_canonicalization.rs +++ b/crates/conceptweave-client/tests/digest_canonicalization.rs @@ -5,7 +5,7 @@ fn uppercase_sha256_digest_identity_is_rejected() { let uppercase_digest = format!("sha256:{}", "A".repeat(64)); assert_eq!( - ReleaseDigest::new(uppercase_digest), + ReleaseDigest::new(&uppercase_digest), Err(ReleaseContractError::InvalidDigest) ); } diff --git a/crates/conceptweave-client/tests/documentation_contract.rs b/crates/conceptweave-client/tests/documentation_contract.rs index 1ce94b97..cea0d1a3 100644 --- a/crates/conceptweave-client/tests/documentation_contract.rs +++ b/crates/conceptweave-client/tests/documentation_contract.rs @@ -3,7 +3,7 @@ const PRD: &str = include_str!("../../../docs/PRD.md"); const TRD: &str = include_str!("../../../docs/TRD.md"); const UML: &str = include_str!("../../../docs/UML.md"); -const ADR: &str = include_str!("../../../docs/adr/0004-semantic-release-client-boundary.md"); +const ADR: &str = include_str!("../../../docs/adr/0005-semantic-release-client-boundary.md"); const GAP_BASELINE: &str = include_str!("../../../docs/product-technical-gap-baseline.md"); const TEST_STRATEGY: &str = include_str!("../../../TEST_STRATEGY.md"); const SECURITY: &str = include_str!("../../../SECURITY.md"); @@ -14,7 +14,7 @@ fn retired_serialized_artifact_api_is_absent_from_public_docs() { ("PRD", PRD), ("TRD", TRD), ("UML", UML), - ("ADR 0004", ADR), + ("ADR 0005", ADR), ("gap baseline", GAP_BASELINE), ("test strategy", TEST_STRATEGY), ("security", SECURITY), @@ -32,7 +32,7 @@ fn detached_artifact_integrity_is_documented_as_current_behavior() { ("PRD", PRD), ("TRD", TRD), ("UML", UML), - ("ADR 0004", ADR), + ("ADR 0005", ADR), ("gap baseline", GAP_BASELINE), ("test strategy", TEST_STRATEGY), ("security", SECURITY), diff --git a/crates/conceptweave-client/tests/release_compatibility.rs b/crates/conceptweave-client/tests/release_compatibility.rs index 382be413..0926e17d 100644 --- a/crates/conceptweave-client/tests/release_compatibility.rs +++ b/crates/conceptweave-client/tests/release_compatibility.rs @@ -41,6 +41,14 @@ fn client_explicitly_distinguishes_current_supported_legacy_and_unknown_versions ) .expect("explicit compatibility policy is valid"); + assert_eq!( + client + .supported_legacy_contract_versions() + .iter() + .map(String::as_str) + .collect::>(), + vec!["1.0.0", "1.1.0"] + ); assert_eq!( client.compatibility(&release("2.0.0")), ContractVersionCompatibility::Current diff --git a/crates/conceptweave-client/tests/release_supersession.rs b/crates/conceptweave-client/tests/release_supersession.rs index b88a9282..f76db023 100644 --- a/crates/conceptweave-client/tests/release_supersession.rs +++ b/crates/conceptweave-client/tests/release_supersession.rs @@ -14,7 +14,7 @@ fn evidence() -> EvidenceReference { } fn digest(hex: char) -> ReleaseDigest { - ReleaseDigest::new(format!("sha256:{}", hex.to_string().repeat(64))) + ReleaseDigest::new(&format!("sha256:{}", hex.to_string().repeat(64))) .expect("digest fixture is valid") } diff --git a/docs/adr/0004-semantic-release-client-boundary.md b/docs/adr/0005-semantic-release-client-boundary.md similarity index 99% rename from docs/adr/0004-semantic-release-client-boundary.md rename to docs/adr/0005-semantic-release-client-boundary.md index db7850ba..c1d52847 100644 --- a/docs/adr/0004-semantic-release-client-boundary.md +++ b/docs/adr/0005-semantic-release-client-boundary.md @@ -1,4 +1,4 @@ -# ADR 0004 — Semantic-release client boundary +# ADR 0005 — Semantic-release client boundary - **Status:** Proposed - **Date:** 2026-09-02 diff --git a/docs/adr/README.md b/docs/adr/README.md index 0d32a43c..9b8cff1e 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -3,4 +3,4 @@ - [ADR 0001 — Product and bounded-context boundary](0001-product-boundary.md) - [ADR 0002 — Evidence, truth, and publication lifecycle](0002-truth-publication-lifecycle.md) - [ADR 0003 — Standards and LLM engineering boundary](0003-standards-llm-boundary.md) -- [ADR 0004 — Semantic-release client boundary](0004-semantic-release-client-boundary.md) — Proposed +- [ADR 0005 — Semantic-release client boundary](0005-semantic-release-client-boundary.md) — Proposed diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index bedacd5e..63a16a50 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -23,7 +23,7 @@ Predecessor reviews/checks never transfer to successor heads. No force-push, des | Product boundary | ACTIVE_PR | PRD/TRD/ADR/context map define ConceptWeave ownership of `observe -> discover -> propose -> align -> validate -> review -> publish`, governed immutable semantic releases and stable Client contracts. Foreign product truth remains behind released/versioned ports and ACLs. | | Truth/publication lifecycle | REPAIRED_PENDING_CI | Rust already derives truth status from publication state. The public JSON Schema now enforces the same mapping for every state, preventing pre-publication `authoritative` claims by non-Rust consumers. New invalid fixture proves the previously admitted Draft+Authoritative combination. Hosted exact-head Product evidence is still non-terminal. | | Source Observation | ACTIVE_CHILD | Immutable PostgreSQL table/column/PK/unique/FK/CHECK evidence, exact identifiers, canonical snapshot digest syntax, UTC provenance, receipts, bounded request budgets/cancellation and opaque source registry keys exist. Registry-key consistency at the immutable snapshot boundary is the current semantic TDD lane. No live PostgreSQL adapter is claimed; ADR 0004 remains Proposed. | -| Client Consumption | ACTIVE_CHILD | Offline Published+Authoritative admission, compatibility, exact resolution/diff, canonical digest verification, detached artifact verification and explicit supersession validation exist. Public supersession/publication schema/fixtures remain the next Client contract lane after Foundation terminal quality. | +| Client Consumption | ACTIVE_CHILD | Offline Published+Authoritative admission, compatibility, exact resolution/diff, canonical digest validation, `verify_detached_artifact` byte-integrity verification and explicit supersession validation exist. Public supersession/publication schema/fixtures remain the next Client contract lane after Foundation terminal quality. | | Quality gate | ACTIVE_PR | Rust 1.98.0, unsafe forbidden, public docs required, exact checkout, fmt, Clippy, tests, rustdoc, owned 100% coverage, Draft-2020-12 schema fixtures, lock freshness and clean-tree checks. Every head movement requires fresh exact-head evidence. | | Security / dependency review | BLOCKED_OWNER | Prior Security evidence showed authoritative GitHub Dependency Review availability was not satisfied. `.github#810` owns central repair; scanner substitution and 403-as-success are forbidden. | | Review / runner admission | BLOCKED_OWNER | Central queue pressure is materially lower than its peak but current ConceptWeave canaries remain non-terminal. `.github#712/#1531/#1796` own central admission/review-amplification. Queue depth alone is not consumer GREEN. | diff --git a/scripts/check_coverage.sh b/scripts/check_coverage.sh index 2f691898..7cf6320a 100755 --- a/scripts/check_coverage.sh +++ b/scripts/check_coverage.sh @@ -2,7 +2,7 @@ set -euo pipefail coverage_toolchain="${COVERAGE_TOOLCHAIN:-nightly-2026-08-20}" -trap 'rm -f coverage.json source-branches.json' EXIT +trap 'rm -f coverage.json source-branches.json source-regions.json' EXIT cargo "+${coverage_toolchain}" llvm-cov \ --workspace \ @@ -21,6 +21,49 @@ jq -r ' | "COVERAGE_GAP file=\(.filename) lines=\(.summary.lines.percent) functions=\(.summary.functions.percent) regions=\(.summary.regions.percent)" ' coverage.json +jq ' + [ + .data[0].functions[] + | .filenames as $files + | .regions[] + | select(.[6] == 0) + | { + file: $files[.[5]], + line_start: .[0], + column_start: .[1], + line_end: .[2], + column_end: .[3], + count: .[4] + } + | select(.file | contains("/tests/") | not) + ] + | sort_by(.file, .line_start, .column_start, .line_end, .column_end) + | group_by([.file, .line_start, .column_start, .line_end, .column_end]) + | map({ + file: .[0].file, + line_start: .[0].line_start, + column_start: .[0].column_start, + line_end: .[0].line_end, + column_end: .[0].column_end, + count: (map(.count) | add) + }) +' coverage.json > source-regions.json + +jq ' + { + count: length, + covered: ([.[] | select(.count > 0)] | length), + notcovered: ([.[] | select(.count == 0)] | length) + } + | .percent = (if .count == 0 then 100 else (.covered * 100 / .count) end) +' source-regions.json + +jq -r ' + .[] + | select(.count == 0) + | "REGION_GAP file=\(.file) start=\(.line_start):\(.column_start) end=\(.line_end):\(.column_end)" +' source-regions.json + jq ' [ .data[0].files[] @@ -66,8 +109,8 @@ jq -r ' jq -e ' .data[0].totals.lines.percent == 100 and - .data[0].totals.functions.percent == 100 and - .data[0].totals.regions.percent == 100 + .data[0].totals.functions.percent == 100 ' coverage.json >/dev/null +jq -e 'all(.[]; .count > 0)' source-regions.json >/dev/null jq -e 'all(.[]; .true_count > 0 and .false_count > 0)' source-branches.json >/dev/null From 0087f6c8bdafcc9fb08eb14f962597b07560272d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 23:23:36 +0900 Subject: [PATCH 58/67] fix(client): publish supersession JSON contract --- ...c-release-supersession.invalid-digest.json | 11 ++++++ ...elease-supersession.invalid-rationale.json | 11 ++++++ .../semantic-release-supersession.valid.json | 11 ++++++ .../semantic-release-supersession.schema.json | 35 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 contracts/fixtures/semantic-release-supersession.invalid-digest.json create mode 100644 contracts/fixtures/semantic-release-supersession.invalid-rationale.json create mode 100644 contracts/fixtures/semantic-release-supersession.valid.json create mode 100644 contracts/semantic-release-supersession.schema.json diff --git a/contracts/fixtures/semantic-release-supersession.invalid-digest.json b/contracts/fixtures/semantic-release-supersession.invalid-digest.json new file mode 100644 index 00000000..fc8f4068 --- /dev/null +++ b/contracts/fixtures/semantic-release-supersession.invalid-digest.json @@ -0,0 +1,11 @@ +{ + "superseded": { + "release_id": "semantic_release_2026_09", + "artifact_digest": "sha256:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + }, + "successor": { + "release_id": "semantic_release_2026_10", + "artifact_digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + "rationale": "Correct the governed control taxonomy while preserving the prior release." +} diff --git a/contracts/fixtures/semantic-release-supersession.invalid-rationale.json b/contracts/fixtures/semantic-release-supersession.invalid-rationale.json new file mode 100644 index 00000000..1034f4d4 --- /dev/null +++ b/contracts/fixtures/semantic-release-supersession.invalid-rationale.json @@ -0,0 +1,11 @@ +{ + "superseded": { + "release_id": "semantic_release_2026_09", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "successor": { + "release_id": "semantic_release_2026_10", + "artifact_digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + "rationale": " " +} diff --git a/contracts/fixtures/semantic-release-supersession.valid.json b/contracts/fixtures/semantic-release-supersession.valid.json new file mode 100644 index 00000000..0ec6f668 --- /dev/null +++ b/contracts/fixtures/semantic-release-supersession.valid.json @@ -0,0 +1,11 @@ +{ + "superseded": { + "release_id": "semantic_release_2026_09", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "successor": { + "release_id": "semantic_release_2026_10", + "artifact_digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + "rationale": "Correct the governed control taxonomy while preserving the prior release." +} diff --git a/contracts/semantic-release-supersession.schema.json b/contracts/semantic-release-supersession.schema.json new file mode 100644 index 00000000..59ac0a22 --- /dev/null +++ b/contracts/semantic-release-supersession.schema.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.contextualwisdomlab.org/conceptweave/semantic-release-supersession/1.0.0", + "title": "ConceptWeave Semantic Release Supersession", + "type": "object", + "additionalProperties": false, + "required": ["superseded", "successor", "rationale"], + "properties": { + "superseded": {"$ref": "#/$defs/release_reference"}, + "successor": {"$ref": "#/$defs/release_reference"}, + "rationale": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + } + }, + "$defs": { + "release_reference": { + "type": "object", + "additionalProperties": false, + "required": ["release_id", "artifact_digest"], + "properties": { + "release_id": { + "type": "string", + "minLength": 1, + "pattern": ".*\\S.*" + }, + "artifact_digest": { + "type": "string", + "pattern": "^sha256:[0-9a-f]{64}$" + } + } + } + } +} From 6cf136b94b76e09c8ec1c15fee809fe5ca791dca Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 23:54:12 +0900 Subject: [PATCH 59/67] test(client): cover immutable release review findings --- .../tests/review_contract_regressions.rs | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 crates/conceptweave-client/tests/review_contract_regressions.rs diff --git a/crates/conceptweave-client/tests/review_contract_regressions.rs b/crates/conceptweave-client/tests/review_contract_regressions.rs new file mode 100644 index 00000000..4d1b03ef --- /dev/null +++ b/crates/conceptweave-client/tests/review_contract_regressions.rs @@ -0,0 +1,129 @@ +use conceptweave_client::{ + ReleaseDigest, ReleaseMetadata, ReleaseSupersession, SemanticRelease, SemanticReleaseClient, + SemanticReleaseReference, +}; +use conceptweave_domain::{EvidenceReference, PublicationState, TruthStatus}; +use std::{fs, path::PathBuf}; + +fn digest(hex: char) -> ReleaseDigest { + ReleaseDigest::new(&format!("sha256:{}", hex.to_string().repeat(64))) + .expect("digest fixture must be canonical") +} + +fn evidence() -> EvidenceReference { + EvidenceReference::new( + "snapshot:client-review-regression", + "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "governance_core.control_evidence.control_identifier", + ) + .expect("evidence fixture must be valid") +} + +fn release( + release_id: &str, + digest_hex: char, + truth_status: TruthStatus, + publication_state: PublicationState, + concept_ids: &[&str], +) -> SemanticRelease { + SemanticRelease::new( + ReleaseMetadata::new(release_id, "1.0.0", "ontology_client_review") + .expect("metadata fixture must be valid"), + truth_status, + publication_state, + digest(digest_hex), + vec![evidence()], + concept_ids.iter().map(|value| (*value).to_owned()).collect(), + ) + .expect("release fixture must be structurally valid") +} + +fn repository_root() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .parent() + .and_then(|path| path.parent()) + .expect("client crate must live below the repository root") + .to_path_buf() +} + +#[test] +fn diff_fails_closed_when_one_release_id_names_conflicting_immutable_content() { + let client = SemanticReleaseClient::new("1.0.0").expect("client policy must be valid"); + let previous = release( + "semantic_release_same_id", + 'b', + TruthStatus::Authoritative, + PublicationState::Published, + &["control.evidence"], + ); + let conflicting = release( + "semantic_release_same_id", + 'c', + TruthStatus::Authoritative, + PublicationState::Published, + &["control.owner"], + ); + + assert!( + client.diff(&previous, &conflicting).is_err(), + "one stable release id must not be treated as ordinary evolution when its immutable content conflicts" + ); +} + +#[test] +fn supersession_accepts_the_governed_superseded_predecessor_state() { + let client = SemanticReleaseClient::new("1.0.0").expect("client policy must be valid"); + let previous = release( + "semantic_release_previous", + 'b', + TruthStatus::Superseded, + PublicationState::Superseded, + &["control.evidence"], + ); + let successor = release( + "semantic_release_successor", + 'c', + TruthStatus::Authoritative, + PublicationState::Published, + &["control.evidence", "control.owner"], + ); + let declaration = ReleaseSupersession::new( + SemanticReleaseReference::from_release(&previous), + SemanticReleaseReference::from_release(&successor), + "steward-approved immutable correction", + ) + .expect("supersession declaration must be valid"); + + assert_eq!( + client.validate_supersession(&declaration, &previous, &successor), + Ok(()), + "supersession validation must accept the predecessor after Governance marks it Superseded" + ); +} + +#[test] +fn public_contract_and_coverage_gates_encode_the_reviewed_fail_closed_rules() { + let root = repository_root(); + let release_schema = fs::read_to_string(root.join("contracts/semantic-release.schema.json")) + .expect("semantic-release schema must exist"); + let product_workflow = fs::read_to_string(root.join(".github/workflows/product.yml")) + .expect("Product workflow must exist"); + let coverage_gate = fs::read_to_string(root.join("scripts/check_coverage.sh")) + .expect("coverage gate must exist"); + + assert!( + release_schema.contains("\"contract_version\"") + && release_schema.contains("\"const\": \"1.0.0\""), + "the versioned 1.0.0 schema must reject unknown contract_version values" + ); + assert!( + product_workflow.contains("semantic-release-supersession.invalid-self.json") + && product_workflow.contains("validate_semantic_release_supersession"), + "the public contract gate must exercise a language-neutral self-supersession negative fixture through an explicit semantic validator" + ); + assert!( + !coverage_gate.contains("select(.[6] == 0)") + && coverage_gate.contains(".data[0].totals.regions.percent == 100"), + "coverage must retain expansion regions and independently enforce LLVM total region coverage" + ); +} From af1d123c2e22c13a514ed15f51d4c3cbc2d50dd9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:52:27 +0900 Subject: [PATCH 60/67] fix(client): bind v1 semantic release schema --- contracts/semantic-release.schema.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/semantic-release.schema.json b/contracts/semantic-release.schema.json index ebea6ff0..a9f30803 100644 --- a/contracts/semantic-release.schema.json +++ b/contracts/semantic-release.schema.json @@ -21,9 +21,7 @@ "pattern": ".*\\S.*" }, "contract_version": { - "type": "string", - "minLength": 1, - "pattern": ".*\\S.*" + "const": "1.0.0" }, "ontology_version": { "type": "string", From 1ac0758d84da8d8c5200cd18c1cfe9eabdda9485 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:52:53 +0900 Subject: [PATCH 61/67] fix(ci): retain expansion regions in coverage gate --- scripts/check_coverage.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/check_coverage.sh b/scripts/check_coverage.sh index 7cf6320a..8d0c5860 100755 --- a/scripts/check_coverage.sh +++ b/scripts/check_coverage.sh @@ -26,7 +26,7 @@ jq ' .data[0].functions[] | .filenames as $files | .regions[] - | select(.[6] == 0) + | select(.[7] == 0 or .[7] == 1) | { file: $files[.[5]], line_start: .[0], @@ -109,7 +109,8 @@ jq -r ' jq -e ' .data[0].totals.lines.percent == 100 and - .data[0].totals.functions.percent == 100 + .data[0].totals.functions.percent == 100 and + .data[0].totals.regions.percent == 100 ' coverage.json >/dev/null jq -e 'all(.[]; .count > 0)' source-regions.json >/dev/null From e54a0b3056c3e551aca86dfc14f95333843497f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:53:56 +0900 Subject: [PATCH 62/67] fix(client): enforce language-neutral supersession semantics --- .github/workflows/product.yml | 7 ++ ...tic-release-supersession.invalid-self.json | 11 ++++ .../semantic-release-supersession.rules.json | 13 ++++ .../validate_semantic_release_supersession.py | 64 +++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 contracts/fixtures/semantic-release-supersession.invalid-self.json create mode 100644 contracts/semantic-release-supersession.rules.json create mode 100644 scripts/validate_semantic_release_supersession.py diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index bef62411..765ceba1 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -132,6 +132,13 @@ jobs: -s contracts/semantic-release-supersession.schema.json \ -d contracts/fixtures/semantic-release-supersession.invalid-rationale.json \ --invalid + python3 scripts/validate_semantic_release_supersession.py \ + contracts/fixtures/semantic-release-supersession.valid.json + if python3 scripts/validate_semantic_release_supersession.py \ + contracts/fixtures/semantic-release-supersession.invalid-self.json; then + echo "::error::self-supersession fixture unexpectedly passed semantic validation" + exit 1 + fi - name: Lockfile freshness run: | diff --git a/contracts/fixtures/semantic-release-supersession.invalid-self.json b/contracts/fixtures/semantic-release-supersession.invalid-self.json new file mode 100644 index 00000000..a31a1dc5 --- /dev/null +++ b/contracts/fixtures/semantic-release-supersession.invalid-self.json @@ -0,0 +1,11 @@ +{ + "superseded": { + "release_id": "semantic_release_same_identity", + "artifact_digest": "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "successor": { + "release_id": "semantic_release_same_identity", + "artifact_digest": "sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" + }, + "rationale": "Invalid fixture: one stable release identity cannot supersede itself." +} diff --git a/contracts/semantic-release-supersession.rules.json b/contracts/semantic-release-supersession.rules.json new file mode 100644 index 00000000..4c5b2fc2 --- /dev/null +++ b/contracts/semantic-release-supersession.rules.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.contextualwisdomlab.org/conceptweave/semantic-release-supersession/1.0.0/semantic-rules", + "contract_version": "1.0.0", + "rules": [ + { + "id": "distinct_release_id", + "operator": "not_equal", + "left": "/superseded/release_id", + "right": "/successor/release_id" + } + ] +} diff --git a/scripts/validate_semantic_release_supersession.py b/scripts/validate_semantic_release_supersession.py new file mode 100644 index 00000000..a730c988 --- /dev/null +++ b/scripts/validate_semantic_release_supersession.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +"""Apply language-neutral semantic rules to a supersession JSON contract.""" + +from __future__ import annotations + +import json +import sys +from pathlib import Path +from typing import Any + + +REPOSITORY_ROOT = Path(__file__).resolve().parents[1] +RULES_PATH = REPOSITORY_ROOT / "contracts" / "semantic-release-supersession.rules.json" + + +def _pointer(document: Any, pointer: str) -> Any: + value = document + for token in pointer.removeprefix("/").split("/"): + if not token: + continue + token = token.replace("~1", "/").replace("~0", "~") + if not isinstance(value, dict) or token not in value: + raise ValueError(f"missing semantic-rule coordinate: {pointer}") + value = value[token] + return value + + +def validate_semantic_release_supersession(document: Any, rules: Any) -> list[str]: + """Return deterministic semantic-rule violations for one public contract.""" + violations: list[str] = [] + for rule in rules.get("rules", []): + if rule.get("operator") != "not_equal": + violations.append(f"unsupported semantic rule operator: {rule.get('operator')!r}") + continue + left = _pointer(document, rule["left"]) + right = _pointer(document, rule["right"]) + if left == right: + violations.append(rule["id"]) + return violations + + +def main(argv: list[str]) -> int: + if len(argv) != 2: + print("usage: validate_semantic_release_supersession.py CONTRACT.json", file=sys.stderr) + return 2 + + contract_path = Path(argv[1]) + try: + document = json.loads(contract_path.read_text(encoding="utf-8")) + rules = json.loads(RULES_PATH.read_text(encoding="utf-8")) + violations = validate_semantic_release_supersession(document, rules) + except (OSError, json.JSONDecodeError, KeyError, TypeError, ValueError) as error: + print(f"semantic supersession validation failed closed: {error}", file=sys.stderr) + return 2 + + if violations: + for violation in violations: + print(f"semantic supersession violation: {violation}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv)) From 663e52d69d878c19091a44b929b0c80abec3d141 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:56:06 +0900 Subject: [PATCH 63/67] fix(client): fail closed on immutable release conflicts --- crates/conceptweave-client/src/lib.rs | 56 ++++++++++++++++++++------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/crates/conceptweave-client/src/lib.rs b/crates/conceptweave-client/src/lib.rs index 086251bd..0edc2dbe 100644 --- a/crates/conceptweave-client/src/lib.rs +++ b/crates/conceptweave-client/src/lib.rs @@ -388,12 +388,7 @@ impl SemanticReleaseClient { } } - /// Fails closed unless a release is explicitly compatible, Published and Authoritative. - /// - /// This check is deterministic and performs no network or model calls. It is - /// suitable as an admission gate before a consuming product performs its own - /// tenant/purpose authorization and physical query planning. - pub fn validate_for_authoritative_use( + fn validate_contract_compatibility( &self, release: &SemanticRelease, ) -> Result<(), ReleaseContractError> { @@ -403,6 +398,19 @@ impl SemanticReleaseClient { actual: release.contract_version().to_string(), }); } + Ok(()) + } + + /// Fails closed unless a release is explicitly compatible, Published and Authoritative. + /// + /// This check is deterministic and performs no network or model calls. It is + /// suitable as an admission gate before a consuming product performs its own + /// tenant/purpose authorization and physical query planning. + pub fn validate_for_authoritative_use( + &self, + release: &SemanticRelease, + ) -> Result<(), ReleaseContractError> { + self.validate_contract_compatibility(release)?; if release.publication_state != PublicationState::Published { return Err(ReleaseContractError::ReleaseNotPublished { actual: release.publication_state, @@ -469,18 +477,26 @@ impl SemanticReleaseClient { Ok(()) } - /// Validates an explicit immutable supersession declaration between two admitted releases. + /// Validates an explicit immutable supersession declaration between two governed releases. /// - /// Both releases must independently pass the normal authoritative-use gate. The declaration - /// must then match each exact release id and artifact digest. No version order, timestamp, - /// content diff, or ontology similarity is treated as implicit supersession evidence. + /// The successor must pass ordinary authoritative-use admission. The predecessor may either + /// still be the admitted Published+Authoritative release while a replacement is reviewed, or + /// already carry the governed Superseded+Superseded lifecycle state after publication of the + /// replacement. In both cases contract compatibility and exact id-and-digest binding remain + /// fail-closed; no version order, timestamp, diff, or ontology similarity is implicit evidence. pub fn validate_supersession( &self, declaration: &ReleaseSupersession, superseded: &SemanticRelease, successor: &SemanticRelease, ) -> Result<(), ReleaseContractError> { - self.validate_for_authoritative_use(superseded)?; + if superseded.publication_state() == PublicationState::Superseded + && superseded.truth_status() == TruthStatus::Superseded + { + self.validate_contract_compatibility(superseded)?; + } else { + self.validate_for_authoritative_use(superseded)?; + } self.validate_for_authoritative_use(successor)?; if declaration.superseded() != &SemanticReleaseReference::from_release(superseded) { @@ -495,9 +511,9 @@ impl SemanticReleaseClient { /// Compares two admitted releases and reports deterministic concept changes. /// /// Both releases pass the same authoritative-use admission gate before any - /// difference is exposed. This prevents diff inspection from becoming a - /// compatibility or publication-state bypass. Concept identifiers are sorted - /// deterministically so the result is reproducible offline. + /// difference is exposed. Reusing one stable release identity for conflicting + /// immutable content fails closed rather than being reported as ordinary + /// evolution. Concept identifiers are sorted deterministically for replay. pub fn diff( &self, previous: &SemanticRelease, @@ -506,6 +522,12 @@ impl SemanticReleaseClient { self.validate_for_authoritative_use(previous)?; self.validate_for_authoritative_use(current)?; + if previous.release_id() == current.release_id() && previous != current { + return Err(ReleaseContractError::ConflictingReleaseIdentity( + previous.release_id().to_owned(), + )); + } + let previous_concepts: BTreeSet<&str> = previous.concept_ids().iter().map(String::as_str).collect(); let current_concepts: BTreeSet<&str> = @@ -558,6 +580,8 @@ pub enum ReleaseContractError { CurrentContractVersionMarkedLegacy(String), /// A release attempted to supersede the same stable release identity. SelfSupersession(String), + /// One stable release identity was reused for conflicting immutable content. + ConflictingReleaseIdentity(String), /// The declared superseded id-and-digest reference does not match the supplied release. SupersededReleaseReferenceMismatch, /// The declared successor id-and-digest reference does not match the supplied release. @@ -608,6 +632,10 @@ impl fmt::Display for ReleaseContractError { formatter, "semantic release `{release_id}` cannot supersede itself" ), + Self::ConflictingReleaseIdentity(release_id) => write!( + formatter, + "semantic release `{release_id}` identifies conflicting immutable content" + ), Self::SupersededReleaseReferenceMismatch => write!( formatter, "supersession predecessor reference does not match the exact supplied release" From d66900512a179406a869f9bc8dd460f2cf789464 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 00:56:22 +0900 Subject: [PATCH 64/67] test(client): cover immutable identity conflict error --- crates/conceptweave-client/tests/error_messages.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/conceptweave-client/tests/error_messages.rs b/crates/conceptweave-client/tests/error_messages.rs index 3fa0c2e4..b26f8586 100644 --- a/crates/conceptweave-client/tests/error_messages.rs +++ b/crates/conceptweave-client/tests/error_messages.rs @@ -37,6 +37,13 @@ fn contract_errors_explain_the_failed_admission_invariant() { ReleaseContractError::SelfSupersession("semantic_release_2026_09".to_string()), "semantic release `semantic_release_2026_09` cannot supersede itself".to_string(), ), + ( + ReleaseContractError::ConflictingReleaseIdentity( + "semantic_release_2026_09".to_string(), + ), + "semantic release `semantic_release_2026_09` identifies conflicting immutable content" + .to_string(), + ), ( ReleaseContractError::SupersededReleaseReferenceMismatch, "supersession predecessor reference does not match the exact supplied release" From 475000ed50aaedf77ad6cc5c1e5664fb7d4c5dc8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 01:01:06 +0900 Subject: [PATCH 65/67] docs(client): reconcile immutable contract boundary --- .../0005-semantic-release-client-boundary.md | 58 +++++++++---------- docs/product-technical-gap-baseline.md | 54 ++++++++--------- 2 files changed, 54 insertions(+), 58 deletions(-) diff --git a/docs/adr/0005-semantic-release-client-boundary.md b/docs/adr/0005-semantic-release-client-boundary.md index c1d52847..ea13ae20 100644 --- a/docs/adr/0005-semantic-release-client-boundary.md +++ b/docs/adr/0005-semantic-release-client-boundary.md @@ -7,71 +7,71 @@ ## Context -Issue #3 requires downstream CWL products to consume governed ConceptWeave releases without importing generation internals. The foundation separates candidate truth from publication state, but a buyer-facing workflow remains incomplete until a consumer can reject incompatible or non-governed releases, verify exact detached artifact bytes, compare releases, and follow an explicit correction/supersession relation without guessing from version order or timestamps. +Issue #3 requires downstream CWL products to consume governed ConceptWeave releases without importing generation internals. The foundation separates candidate truth from publication state, but a buyer-facing workflow is incomplete until a consumer can reject incompatible or non-governed releases, verify exact detached artifact bytes, compare releases, and follow an explicit correction/supersession relation without guessing from version order or timestamps. -A client contract must remain useful offline. LLM/provider availability, generator prompts, persistence state, and foreign application databases cannot be prerequisites for deterministic release admission. Conversely, client-side structural checks must not be confused with publication authority, consuming-product authorization, or cryptographic/signature verification that has not actually occurred. +The Client contract must remain useful offline. LLM/provider availability, generator prompts, persistence state, and foreign application databases are not prerequisites for deterministic release admission. Client-side validation also must not be confused with publication authority, tenant/purpose authorization, or cryptographic evidence that was not actually verified. -This ADR remains **Proposed** while PR #5 is Draft and exact-head Product/security/review evidence is incomplete. Implemented code on an unintegrated Draft head is evidence for the decision, not grounds to mark the decision Accepted prematurely. +This ADR remains **Proposed** while PR #5 is Draft and exact-head Product/security/review evidence is incomplete. Code on an unintegrated head is decision evidence, not grounds for premature Accepted status. ## Decision Introduce **Client Consumption** as a Supporting Bounded Context and `conceptweave-client` as its Rust reference implementation. -The current `semantic_release` public contract carries stable release identity, explicit contract and ontology/model versions, truth/publication state, a canonical declared artifact digest identity, provenance references, and unique stable concept identifiers. `SemanticReleaseClient` admits authoritative use only when the release uses the explicit current contract version or an explicitly configured supported-legacy version and is both `Published` and `Authoritative`. Compatibility is never inferred from semantic-version ordering. +The versioned `semantic_release` contract carries stable release identity, explicit contract and ontology/model versions, truth/publication state, canonical declared artifact digest identity, provenance references, and unique stable concept identifiers. The v1 public JSON Schema is bound to `contract_version = 1.0.0`; unknown/future versions cannot validate as v1. `SemanticReleaseClient` admits authoritative use only when the release is explicitly compatible and both `Published` and `Authoritative`. Compatibility is never inferred from semantic-version ordering. -`ReleaseDigest` accepts only canonical `sha256:<64 lowercase hex>` identity. `SemanticReleaseClient::verify_detached_artifact` separately hashes the exact caller-supplied detached immutable semantic-artifact bytes and requires an exact digest match after authoritative-use admission. The manifest declares that detached artifact digest; the contract deliberately avoids a self-referential requirement to hash the manifest bytes containing the digest field. Digest syntax and byte-integrity evidence therefore remain distinct. +`ReleaseDigest` accepts only canonical `sha256:<64 lowercase hex>`. `SemanticReleaseClient::verify_detached_artifact` separately hashes the caller-supplied detached immutable artifact bytes and requires an exact digest match after authoritative-use admission. Digest syntax and byte-integrity evidence remain distinct. -`SemanticReleaseClient::diff` admits both releases through the same authoritative-use gate and reports deterministic sorted concept additions/removals. Exact concept resolution is deterministic and performs no fuzzy matching or model call. +`SemanticReleaseClient::diff` admits both releases through the authoritative-use gate and reports deterministic sorted concept additions/removals. If one stable `release_id` names conflicting immutable release content, diff fails closed instead of representing the conflict as ordinary evolution. Exact concept resolution remains deterministic and performs no fuzzy matching or model call. -For corrections, `SemanticReleaseReference` binds one release id to its exact artifact digest. `ReleaseSupersession` names a distinct superseded reference, an exact successor reference, and a nonblank rationale. `validate_supersession` requires both referenced releases to pass ordinary authoritative-use admission and requires both id-and-digest references to match exactly. Supersession is never inferred from version order, timestamp, semantic diff, or ontology similarity, and the prior immutable release is not overwritten. +For corrections, `SemanticReleaseReference` binds one release id to its exact artifact digest. `ReleaseSupersession` names a distinct predecessor reference, exact successor reference, and nonblank rationale. `validate_supersession` accepts a predecessor that is still Published+Authoritative while replacement is being governed or one that has already moved to the governed Superseded+Superseded lifecycle state; the successor must pass ordinary Published+Authoritative admission. Both id-and-digest references must match exactly. Supersession is never inferred from version order, timestamp, semantic diff, or ontology similarity, and the prior immutable release is never overwritten. -The generation-to-client seam is a versioned public contract. Client code may use public domain value types such as `TruthStatus`, `PublicationState`, and `EvidenceReference`, but may not import generator-private classes, prompts, provider payloads, persistence tables, Source Observation internals, or orchestration state. +Draft 2020-12 JSON Schema cannot express sibling-field inequality. Therefore the public supersession seam includes `semantic-release-supersession.rules.json`, whose `distinct_release_id` rule is machine-readable and language-neutral, plus a deterministic reference validator and negative fixture. Structural schema validation and semantic cross-field validation are both required conformance steps. -Consuming products keep tenant/purpose authorization, business-domain truth, and physical query execution. ConceptWeave returns semantic contracts/query plans; it does not become a foreign product's data plane. +The generation-to-client seam is a versioned public contract. Client code may use public domain value types such as `TruthStatus`, `PublicationState`, and `EvidenceReference`, but may not import generator-private classes, prompts, provider payloads, persistence tables, Source Observation internals, or orchestration state. -LLM-assisted future `match`, ambiguity explanation, and candidate ranking operations must use `ContextualWisdomLab/contextual-orchestrator`. Their outputs remain candidate/evidence state. Admission, compatibility, digest verification, supersession validation, publication-state checks, and authorization remain deterministic. +Consuming products retain tenant/purpose authorization, business-domain truth, and physical query execution. ConceptWeave returns governed semantic contracts/query plans; it does not become a foreign product's data plane. Any future LLM-assisted match/explain/ranking operation must use released `contextual-orchestrator`; deterministic admission, compatibility, integrity, supersession, publication-state and authorization checks remain outside model authority. ## Consequences ### Positive - consumers can fail closed before authoritative use without an LLM provider; -- stable release contracts prevent generator-private implementation leakage; +- stable public contracts prevent generator-private implementation leakage; - truth/publication authority remains explicit across repository boundaries; - digest syntax and actual byte verification cannot be conflated; -- explicit supported-legacy policy avoids accidental version-order heuristics; -- corrections preserve immutable predecessor releases and bind the exact successor by id plus digest; -- GRC and other downstream consumers can build ACLs against one stable seam. +- version admission is explicit and fail-closed; +- corrections preserve immutable predecessor releases and exact successor identity; +- structural JSON conformance and cross-field semantic conformance are explicit rather than pretending JSON Schema can express unsupported invariants. ### Costs and deferred work -- the Rust supersession contract does not yet have a finalized language-neutral supersession JSON Schema or generated bindings; - signature/provenance-chain verification remains deferred until Governance & Publication defines a stable signing contract; -- typed relation/mapping/dimension/measure resolution, match/align/explain, and semantic query-plan operations remain Issue #3 work; -- GRC reference-client fixtures remain required before buyer-facing integration readiness; +- typed relation/mapping/dimension/measure resolution, match/align/explain and semantic query-plan operations remain Issue #3 work; +- GRC-shaped reference-client fixtures remain required before buyer-facing integration readiness; - this ADR cannot advance to Accepted until the stacked implementation is integrated and current-head deterministic/security/review evidence is terminal. ## Alternatives rejected 1. **Let consumers import generator internals.** Rejected because it couples downstream products to prompts/adapters/persistence and destroys the reuse boundary. -2. **Require an LLM call to decide release usability.** Rejected because compatibility, governance state, digest verification, and explicit supersession are deterministic security/data-integrity controls. +2. **Require an LLM call to decide release usability.** Rejected because compatibility, governance state, digest verification and explicit supersession are deterministic security/data-integrity controls. 3. **Treat a well-shaped digest string as proof of artifact integrity.** Rejected because syntax validation does not hash bytes. -4. **Infer compatibility or supersession from version ordering/timestamps.** Rejected because neither proves compatibility nor steward-approved replacement and would create hidden heuristics. +4. **Infer compatibility or supersession from version ordering/timestamps.** Rejected because neither proves compatibility nor steward-approved replacement. 5. **Overwrite a published release in place when corrected.** Rejected because published semantic truth is immutable; correction creates a distinct successor and explicit supersession evidence. -6. **Move downstream authorization into ConceptWeave.** Rejected because tenant/purpose authorization belongs to each consuming product and its identity/control plane. +6. **Pretend structural JSON Schema enforces self-supersession inequality.** Rejected because Draft 2020-12 has no general sibling-field inequality operator; the semantic rule must remain explicit. +7. **Move downstream authorization into ConceptWeave.** Rejected because tenant/purpose authorization belongs to each consuming product and its identity/control plane. ## Verification evidence on the active branch -- Existing Rust integration tests cover authoritative admission, compatibility, non-Published/non-Authoritative states, provenance/identity requirements, duplicate concepts, digest syntax, exact detached-byte verification, diff, and exact concept resolution. -- Test-first supersession commit `67132eda0e25d23a4185d4b98f0c6dc3b11e17a4` introduced an API that did not yet exist and required immutable id+digest predecessor/successor references, rationale, self-supersession rejection, exact-reference validation, and ordinary authoritative admission. -- Production commit `2c4a7954ad3a4fb0dd0a5482a6870fcc0d2996a3` implements that bounded contract. Follow-up edge coverage binds mismatch checks to digest as well as id and exercises both predecessor and successor admission paths. -- Detached-artifact contract RED was observed on predecessor head `0c32a7b55d3c687ab76cee789962866573496ba1`: Product run `33664177838`, job `100361706615` acquired an Ubuntu 24.04 runner, verified the exact checkout, passed the CI contract/toolchain/fmt steps, then Clippy failed with `E0599` because `verify_detached_artifact` did not yet exist. Production head `9c278598001c502a733100d11e901538c3dc2677` applies only the causal API/rustdoc repair. -- Hosted exact-head GREEN is still required on the final unchanged documentation head; queued/predecessor results are not GREEN. +- Predecessor `61776fbf5969ec4f8897f48b7bd410052f83ea9d` recorded a hosted Product RED for the missing public supersession contract. +- Test-only `6cf136b94b76e09c8ec1c15fee809fe5ca791dca` encodes five reviewed fail-closed regressions: immutable release-id conflict, governed Superseded predecessor admission, v1 schema version binding, self-supersession semantic conformance, and LLVM expansion-region/total-region coverage. +- `af1d123c...`, `1ac0758d...`, `e54a0b30...`, `663e52d6...`, and `d6690051...` apply the corresponding minimal schema, coverage, semantic-rule, Rust and edge-coverage repairs. +- `e0ef02ee99375ebef2ce2b815dc5340e45708b24` non-force adopts Foundation #14 as a two-parent merge and preserves the Client-specific public-contract gate while taking the Foundation repository-qualified PR concurrency/CI contract. +- The semantic reference validator was executed locally against its valid and self-supersession fixtures with return codes 0 and 1 respectively. This is focused local evidence, not hosted exact-head GREEN. ## Follow-up / acceptance for Accepted status -1. Obtain exact-head fmt/Clippy/tests/rustdoc/100% owned coverage and public-contract validation on the final PR #5 head. -2. Integrate the foundation prerequisite, cleanly restack PR #5, and rerun every then-required exact-head workflow. -3. Resolve all valid current-head review findings and satisfy ordinary governance without self-approval or routine bypass. -4. Define a language-neutral supersession/publication receipt contract before generated bindings or cross-language release claims. +1. Obtain exact-head fmt/Clippy/tests/rustdoc/100% owned coverage and public structural+semantic contract validation on one unchanged final PR #5 head. +2. Integrate the Foundation prerequisite, retain the non-force ancestry, and rerun every then-required exact-head workflow. +3. Resolve each valid review thread only after the current implementation is verified; satisfy ordinary governance without self-approval or routine bypass. +4. Add provenance/signature verification only behind an explicit versioned Governance & Publication contract. 5. Prove the seam with an anonymized GRC-shaped reference-client fixture and no cross-service application-table access. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 63a16a50..90da08f9 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,57 +1,53 @@ # Product / Technical Gap Baseline -**Snapshot:** 2026-09-04 +**Snapshot:** 2026-09-05 -This file records code-current product and technical gaps. Exact PR/check/run coordinates below are evidence snapshots, not mutable-head dependencies. Live protected-branch, PR, issue and workflow state wins whenever it advances after this snapshot. Because this documentation update itself creates a successor Foundation head, the Foundation SHA below is explicitly the exact pre-refresh head. +This document records code-current product and technical gaps. Exact heads below are evidence coordinates, not mutable dependencies. Live protected-branch, PR, Issue and workflow state wins whenever it advances. A documentation reconciliation commit necessarily creates a successor head, so the Client coordinate below is the exact pre-documentation head. ## Protected truth and active stack -Protected/default `main` remains `f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425`; only the bootstrap state is shipped there and no immutable ConceptWeave release exists yet. +Protected/default `main` remains `f4f440dd58c77d7cd90dff8a1eb2eeb9a9940425`; only bootstrap state is shipped there and no immutable ConceptWeave release exists. -The active dependency stack observed immediately before this baseline refresh is: - -1. Foundation PR #1 — pre-refresh exact head `9a6aa93ed05dd9cc56825258e072b222d80f85de`, open/non-Draft/mergeable. A public-contract mismatch was reproduced locally before the repair: the Draft 2020-12 `semantic-candidate` schema accepted `publication_state=draft` together with `truth_status=authoritative`, although the Rust domain maps Draft/Validated/Reviewed to Inferred, Proposed to Proposed, Published to Authoritative, Superseded to Superseded and Rejected to Rejected. Test-first `18249652...` added an invalid fixture and Product AJV assertion; minimum fix `9a6aa93...` makes the language-neutral schema enforce the same state/truth mapping as Rust. Local exhaustive verification covered all 7 publication states × 6 truth statuses with zero mapping mismatches. This is local exact-contract GREEN, not hosted exact-head GREEN. Product `33871067722` / job `101016914449`, SAST `33871067759`, and Security `33871067702` remain non-terminal; Product has no executed steps yet. -2. Client Consumption PR #5 — pre-refresh exact head `4a771af962306febb4318aed4de48254d96f32f9`, Draft/open. It non-force adopted the Foundation truth-state contract. The first restack accidentally replaced the child-specific Product JSON-contract checks with the narrower Foundation workflow; that repair finding was fixed immediately by `4a771af...`. Old-child `67c104...` → current comparison now changes only the new candidate mismatch fixture, the candidate schema and five added Product-workflow lines, while all pre-existing semantic-release and supersession checks remain intact. Product `33871312459` is non-terminal. The next Client RED remains its missing language-neutral supersession/publication schema and fixtures after inherited Foundation quality is terminal. -3. Source Observation PR #6 — pre-refresh exact head `e72345ac9f407e5732b3e3cc5a2d78b55b10cad2`, Draft/open. It non-force adopted the same Foundation contract; old-child `a0197ba...` → current comparison changes only the candidate mismatch fixture, candidate schema and five Product-workflow lines. Source Observation semantic delta is preserved. Product `33871231617` is queued. The registry-identity test still requires immutable snapshot/source-receipt provenance to obey the Source Observation port's opaque ≤128-byte lowercase multiword `snake_case` key boundary; production `PostgresSchemaSnapshot::new` still validates this field only as nonblank, so that semantic lane remains open. +- **Foundation PR #1** — `8e8783286eac7567803568d9a91010daaf028074`, open/non-Draft/mergeable. The Foundation includes the public truth/publication-state contract, authoritative research references and repository-qualified Product concurrency repair. Its fresh central required workflows are queued. The exact current head did not expose a repository-owned Product run in the latest Actions generation, so predecessor Product success is not accepted as current GREEN. +- **Client Consumption PR #5** — pre-documentation head `e0ef02ee99375ebef2ce2b815dc5340e45708b24`, Draft/open/mergeable, now directly descended from Foundation `8e878328...` through a non-force two-parent merge. Five reviewed Client regressions have causal repairs: immutable release-id/content conflict; governed Superseded predecessor admission; v1 schema version binding; machine-readable self-supersession semantic conformance; and LLVM expansion/total-region coverage. Exact-head hosted GREEN remains required before review threads or Draft state can be cleared. +- **Source Observation PR #6** — Draft/open. The current semantic findings remain targeted PostgreSQL FK action-column coordinates, a true end-to-end observation deadline, typed invalid-captured-metadata/adapter-construction failure, and registry/ACL-resolved source capability rather than syntax-as-authorization. This lane remains independent of Client implementation details. +- **Research classification chain #9 → #10 → #11 → #12 → #13 → #15 → #16** — all remain Foundation-dependent Draft work. Classification, golden-set evaluation, audit, duplicate manifest, write plan, execution receipts and multilingual abstention evidence are proposed/review evidence only. No Zotero mutation or research-derived semantic label becomes authoritative before steward validation and governed publication. Predecessor reviews/checks never transfer to successor heads. No force-push, destructive rebase, self-approval, fail-open scanner substitution or routine administrator bypass is acceptance evidence. -## Foundation capability status +## Capability status | Area | Status | Evidence / next verification | | --- | --- | --- | | Product boundary | ACTIVE_PR | PRD/TRD/ADR/context map define ConceptWeave ownership of `observe -> discover -> propose -> align -> validate -> review -> publish`, governed immutable semantic releases and stable Client contracts. Foreign product truth remains behind released/versioned ports and ACLs. | -| Truth/publication lifecycle | REPAIRED_PENDING_CI | Rust already derives truth status from publication state. The public JSON Schema now enforces the same mapping for every state, preventing pre-publication `authoritative` claims by non-Rust consumers. New invalid fixture proves the previously admitted Draft+Authoritative combination. Hosted exact-head Product evidence is still non-terminal. | -| Source Observation | ACTIVE_CHILD | Immutable PostgreSQL table/column/PK/unique/FK/CHECK evidence, exact identifiers, canonical snapshot digest syntax, UTC provenance, receipts, bounded request budgets/cancellation and opaque source registry keys exist. Registry-key consistency at the immutable snapshot boundary is the current semantic TDD lane. No live PostgreSQL adapter is claimed; ADR 0004 remains Proposed. | -| Client Consumption | ACTIVE_CHILD | Offline Published+Authoritative admission, compatibility, exact resolution/diff, canonical digest validation, `verify_detached_artifact` byte-integrity verification and explicit supersession validation exist. Public supersession/publication schema/fixtures remain the next Client contract lane after Foundation terminal quality. | -| Quality gate | ACTIVE_PR | Rust 1.98.0, unsafe forbidden, public docs required, exact checkout, fmt, Clippy, tests, rustdoc, owned 100% coverage, Draft-2020-12 schema fixtures, lock freshness and clean-tree checks. Every head movement requires fresh exact-head evidence. | -| Security / dependency review | BLOCKED_OWNER | Prior Security evidence showed authoritative GitHub Dependency Review availability was not satisfied. `.github#810` owns central repair; scanner substitution and 403-as-success are forbidden. | -| Review / runner admission | BLOCKED_OWNER | Central queue pressure is materially lower than its peak but current ConceptWeave canaries remain non-terminal. `.github#712/#1531/#1796` own central admission/review-amplification. Queue depth alone is not consumer GREEN. | -| Standards / research | REPAIRED_PENDING_CI | Doctoring binds He et al. to CEUR/ISWC 2023 and Amini et al. to the Springer LNCS 15459 version of record published in 2025 while retaining KGSWC 2024 study/conference lineage in traceability. Hosted exact-head evidence remains non-terminal. | -| Release | NOT_STARTED | No immutable ConceptWeave release exists. Version/CHANGELOG/tag/package/semantic_release/SBOM/provenance/reproducibility/rollback are required on the exact protected release head. | +| Truth/publication lifecycle | REPAIRED_PENDING_CI | Rust and Draft-2020-12 public schema agree on lifecycle truth mapping; pre-publication authoritative claims fail closed. Exact-head hosted evidence remains required. | +| Client Consumption | REPAIRED_PENDING_CI | Offline admission, compatibility, exact resolution/diff, canonical SHA-256 identity, detached-byte verification, immutable references and explicit supersession exist. v1 contract version is pinned; self-supersession has a machine-readable cross-field rule/negative fixture; conflicting content under one release id fails closed; governed Superseded predecessors are admitted specifically for supersession validation. | +| Source Observation | ACTIVE_CHILD | Immutable relational evidence and bounded source-port contracts exist, but the four current adapter/provenance/deadline/FK findings remain open before a concrete PostgreSQL observation adapter is complete. | +| Research classification | ACTIVE_CHAIN | Read-only Zotero evidence and downstream review artifacts remain proposed. Steward-reviewed quality and safe Zotero 10+ mutation capability are separate gates. | +| Quality gate | ACTIVE_PR | Rust 1.98.0, unsafe forbidden, public docs required, exact checkout, fmt, Clippy, tests, rustdoc, owned 100% line/function/region/branch coverage, public JSON+semantic fixtures, lock freshness and clean-tree checks. Every head movement requires fresh exact-head evidence. | +| Security / dependency review | BLOCKED_OWNER | Central required workflows remain authoritative; scanner substitution and fail-open 403 handling are forbidden. | +| Review / runner admission | BLOCKED_OWNER | Central queue/control-plane work may improve admission, but queue depth or predecessor results are not ConceptWeave acceptance. | +| Standards / research | REPAIRED_PENDING_CI | Doctoring binds He et al. to CEUR/ISWC 2023 and Amini et al. to the Springer LNCS 15459 version of record published in 2025 while retaining KGSWC 2024 study/conference lineage. | +| Release | NOT_STARTED | No immutable release exists. Version/CHANGELOG/tag/package/semantic_release/SBOM/provenance/reproducibility/rollback remain mandatory on the exact protected release head. | ## Central control-plane evidence -Protected central source is `.github/main@c31d2e5471fc5daf9d72ff67cde6a8874b736deb` at this snapshot, after merged #1852 aligned current-main workflow contracts. This is evidence only, not a ConceptWeave dependency. - -- `.github#1821` queue-ownership repair remains integrated: organization sweep no longer owns repository-wide queued/in-progress Actions inventory or broad cancellation; native per-PR concurrency and repository-local exact-head coalescing own supersession. -- Later consolidation removed merge-scheduler required-check fanout, centralized CodeQL PR ownership and consolidated empty-PR/quality lanes. -- Fresh `.github` queued inventory is `245`. This is far below the ~1,900 peak but above some recent lower observations, so it is neither terminal recovery nor consumer acceptance. +Protected `.github/main` is `769691526f8c73cf714de8fe8ba51ae6cfa2901a` at this snapshot. The current central source contains the Strix HTTPX2 runtime/exact OpenAI lock repair and remains a diagnostic/control-plane dependency only; it does not replace ConceptWeave exact-head evidence or semantic ownership. ## P0 product gaps after the current TDD lanes -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. +1. **Concrete Source Observation adapter** — maintained Rust PostgreSQL driver behind `conceptweave-source-port`; adapter-local credential resolution; explicit read-only mode; total operation deadline plus 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. -3. **Semantic-layer discovery** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts; do not infer business authority from relational structure alone. +3. **Semantic-layer discovery** — dimensions, measures, grain, units, relationships and physical mappings with deterministic calculation contracts; relational structure alone never grants business authority. 4. **LLM Proposal** — every production model call through released `contextual-orchestrator`; outputs remain proposed/inferred and preserve source/model/prompt/provenance evidence. 5. **Alignment / matching** — retrieval/pruning/structural evidence first, bounded optional LLM assistance, OAEI-style evaluation, deterministic reproducibility and steward-visible decisions. -6. **Validation engine** — RDF/OWL/SKOS/SHACL and semantic-layer validation, consistency/conflict/duplicate detection, bounded reasoning, explicit unsupported-feature failure. +6. **Validation engine** — RDF/OWL/SKOS/SHACL and semantic-layer validation, consistency/conflict/duplicate detection, bounded reasoning and explicit unsupported-feature failure. 7. **Governance persistence** — PostgreSQL 3NF candidates/evidence/validation/review/release/supersession receipts, transactional outbox and temporal history only where domain semantics require it. 8. **Review workflow** — Keyverse identity context, tenant/role/purpose authorization, steward decisions, maker-checker where required, stale-decision protection and immutable publication receipt. 9. **Publication adapters** — versioned OWL/RDFS/SKOS/SHACL/JSON-LD plus explicitly version-bound Apache Ossie export; draft/incubating formats cannot be presented as final standards. -10. **Client completion** — language-neutral release/supersession contract, provenance/signature verification, relation/mapping/dimension/measure resolution, compatibility/deprecation, match/explain/query-plan contracts while downstream products retain physical authorization/execution. -11. **CWL integration** — only released/versioned semantic_release/contract/ACL seams to `semantic-data-portal`, `context-graph-contracts`, GRC, EA and other consumers; no source copying, cross-service SQL or mutable supplier heads. -12. **Evaluation / multilingual** — reviewed golden fixtures, ontology-learning/matching metrics, source-evidence binding, abstention, reproducibility, KO/EN/JA/ZH/VI/ES/DE/FR labels, CJK/font/text-expansion checks where UI or published labels are material. +10. **Client completion** — provenance/signature verification, relation/mapping/dimension/measure resolution, compatibility/deprecation, match/explain/query-plan contracts and anonymized buyer reference fixtures while downstream products retain physical authorization/execution. +11. **CWL integration** — only released/versioned `semantic_release`/contract/ACL seams to `semantic-data-portal`, `context-graph-contracts`, GRC, EA and other consumers; no source copying, cross-service SQL or mutable supplier heads. +12. **Evaluation / multilingual** — steward-reviewed golden fixtures, ontology-learning/matching metrics, source-evidence binding, abstention, reproducibility, KO/EN/JA/ZH/VI/ES/DE/FR labels, CJK/font/text-expansion checks where UI or published labels are material. 13. **Observability / recovery / release** — structured telemetry, security evidence, backup/restore, package/SBOM/provenance/signing, reproducible build and rollback proof before immutable release. ## DDD fitness constraints @@ -60,6 +56,6 @@ Protected central source is `.github/main@c31d2e5471fc5daf9d72ff67cde6a8874b736d - Adapters remain outside the core domain model; external DTOs cross Anti-Corruption Layers. - Source Observation facts are not source-system business truth, and relational constraints are not semantic authority by themselves. - Client Consumption depends only on governed release contracts, never generator-private classes, prompts, persistence tables or orchestration state. -- `semantic-data-portal` remains catalog/governance/consumption rather than ConceptWeave persistence; `context-graph-contracts` owns interop contracts; `enterprise-architecture-core` owns EA; `contextual-orchestrator` owns provider routing. +- `semantic-data-portal` remains catalog/governance/consumption; `context-graph-contracts` owns interop; `enterprise-architecture-core` owns EA; `contextual-orchestrator` owns provider routing. - Consuming products retain tenant/purpose authorization and physical query execution. - Published semantic truth is immutable; corrections create a new release plus supersession evidence rather than in-place overwrite. From d38c8ef349ea2b19463763465765116a3209ef09 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 07:46:54 +0900 Subject: [PATCH 66/67] ci(client): adopt draft-aware Product admission --- .github/workflows/product.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/product.yml b/.github/workflows/product.yml index bee4d84a..0f683253 100644 --- a/.github/workflows/product.yml +++ b/.github/workflows/product.yml @@ -2,11 +2,12 @@ name: Product on: pull_request: + types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, closed] push: branches: [main] concurrency: - group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }} + group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} permissions: @@ -14,6 +15,7 @@ permissions: jobs: rust-quality: + if: ${{ github.event_name != 'pull_request' || (github.event.action != 'closed' && github.event.pull_request.draft == false) }} runs-on: ubuntu-24.04 env: COVERAGE_TOOLCHAIN: nightly-2026-08-20 From ed55242ecbb6d7d64a7399c7d69150068ecf2c0e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 07:47:01 +0900 Subject: [PATCH 67/67] ci(client): pin draft-aware Product contract --- scripts/check_ci_contract.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/check_ci_contract.py b/scripts/check_ci_contract.py index 1342082b..f23b6c3f 100644 --- a/scripts/check_ci_contract.py +++ b/scripts/check_ci_contract.py @@ -14,8 +14,10 @@ def main() -> int: required_fragments = ( "runs-on: ubuntu-24.04", - "group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event.pull_request.number || github.run_id }}", + "types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, closed]", + "group: ${{ github.workflow }}-${{ github.repository }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }}", "cancel-in-progress: ${{ github.event_name == 'pull_request' }}", + "if: ${{ github.event_name != 'pull_request' || (github.event.action != 'closed' && github.event.pull_request.draft == false) }}", "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0", "COVERAGE_TOOLCHAIN: nightly-2026-08-20", 'rustup toolchain install "$COVERAGE_TOOLCHAIN" --profile minimal --component llvm-tools-preview',