@prefix convo: <https://ontology.inferal.com/modules/conversation/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix prof: <http://www.w3.org/ns/dx/prof/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix role: <http://www.w3.org/ns/dx/prof/role/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

convo:ProvenanceRichProfile
    a prof:Profile ;
    prof:isProfileOf convo: ;
    prof:hasResource <https://ontology.inferal.com/modules/conversation/profiles/provenance-rich#constraints> .

<https://ontology.inferal.com/modules/conversation/profiles/provenance-rich#constraints>
    a prof:ResourceDescriptor ;
    rdfs:label "Provenance-Rich constraints descriptor"@en ;
    rdfs:comment "Describes the SHACL artifact that validates generation, attribution, activity association, derivation, and invalidation completeness."@en ;
    prof:hasArtifact <https://ontology.inferal.com/modules/conversation/profiles/provenance-rich.ttl> ;
    prof:hasRole role:constraints, role:validation ;
    dcterms:conformsTo <http://www.w3.org/ns/shacl#> ;
    dcterms:format <https://www.iana.org/assignments/media-types/text/turtle> .

convo:ProvenanceRichContributionShape
    a sh:NodeShape ;
    rdfs:label "provenance-rich contribution shape"@en ;
    rdfs:comment "Requires explicit generation and attribution and validates reciprocal generation, derivation targets, and invalidation completeness."@en ;
    sh:targetClass convo:Contribution ;
    sh:property [ sh:path prov:wasGeneratedBy ; sh:class prov:Activity ; sh:minCount 1 ] ;
    sh:property [ sh:path prov:wasAttributedTo ; sh:class prov:Agent ; sh:minCount 1 ] ;
    sh:property [ sh:path convo:revisionOf ; sh:class prov:Entity ] ;
    sh:property [ sh:path convo:regenerationOf ; sh:class convo:Contribution ] ;
    sh:property [ sh:path convo:redactedVersionOf ; sh:class prov:Entity ] ;
    sh:property [ sh:path convo:summaryOf ; sh:class prov:Entity ] ;
    sh:sparql [
        sh:message "Each generation activity named by a contribution must point back with prov:generated."@en ;
        sh:select """
            PREFIX prov: <http://www.w3.org/ns/prov#>
            SELECT $this ?activity WHERE {
                $this prov:wasGeneratedBy ?activity .
                FILTER NOT EXISTS { ?activity prov:generated $this . }
            }
        """ ;
    ] ;
    sh:sparql [
        sh:message "Provenance-Rich invalidation must state both prov:invalidatedAtTime and prov:wasInvalidatedBy."@en ;
        sh:select """
            PREFIX prov: <http://www.w3.org/ns/prov#>
            SELECT $this WHERE {
                { $this prov:invalidatedAtTime ?time . FILTER NOT EXISTS { $this prov:wasInvalidatedBy ?activity . } }
                UNION
                { $this prov:wasInvalidatedBy ?activity . FILTER NOT EXISTS { $this prov:invalidatedAtTime ?time . } }
            }
        """ ;
    ] .

convo:ProvenanceRichContributionActShape
    a sh:NodeShape ;
    rdfs:label "provenance-rich contribution act shape"@en ;
    rdfs:comment "Requires each contribution-producing activity to identify a responsible agent and at least one generated contribution."@en ;
    sh:targetClass convo:ContributionAct ;
    sh:property [ sh:path prov:wasAssociatedWith ; sh:class prov:Agent ; sh:minCount 1 ] ;
    sh:property [ sh:path prov:generated ; sh:class convo:Contribution ; sh:minCount 1 ] .
