@prefix jc:    <https://jouleclaw.transaction.science/vocab/v1#> .
@prefix sh:    <http://www.w3.org/ns/shacl#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .

# ─────────────────────────────────────────────────────────────────────
# JouleClaw v1 SHACL shapes
#
# Validates JouleClaw wire forms (cascade Receipt, PolicyReceipt,
# WorkspaceManifest, AgentIdentity, Action, Decision) against the
# v1 vocabulary. Any SHACL validator (pyshacl, Apache Jena, the
# bundled jouleclaw-shacl Rust validator) accepts this shape graph
# as input alongside a candidate document and returns sh:conforms
# plus a list of violations.
#
# The shapes use only the SHACL Core subset, no SPARQL constraints,
# so the lightweight validator in jouleclaw-shacl covers them
# without a SPARQL engine.
# ─────────────────────────────────────────────────────────────────────

# ─── Cascade Receipt (schema "1") ────────────────────────────────────

jc:ReceiptShape a sh:NodeShape ;
    sh:targetClass jc:Receipt ;
    sh:property [ sh:path jc:schemaId          ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ; sh:in ( "1" ) ] ;
    sh:property [ sh:path jc:receiptId         ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:closedAt          ; sh:datatype xsd:dateTime ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:inputHash         ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] ;
    sh:property [ sh:path jc:tier              ; sh:nodeKind sh:IRI       ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:Cache jc:Lawful jc:Embed jc:Model jc:Wire ) ] ;
    sh:property [ sh:path jc:joulesMicrojoules ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:energyProvenance  ; sh:nodeKind sh:IRI       ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:HwShunt jc:ModelBased jc:Estimator ) ] ;
    sh:property [ sh:path jc:steward           ; sh:nodeKind sh:IRI       ; sh:maxCount 1 ] .

# ─── Policy Receipt (schema "policy/1") ──────────────────────────────

jc:PolicyReceiptShape a sh:NodeShape ;
    sh:targetClass jc:PolicyReceipt ;
    sh:property [ sh:path jc:schemaId       ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ; sh:in ( "policy/1" ) ] ;
    sh:property [ sh:path jc:receiptId      ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:closedAt       ; sh:datatype xsd:dateTime ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:steward        ; sh:nodeKind sh:IRI       ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:engineId       ; sh:datatype xsd:string   ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:auditSequence  ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:policyVersion  ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:agent          ; sh:nodeKind sh:IRI       ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:action         ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:node jc:ActionShape ] ;
    sh:property [ sh:path jc:decision       ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:node jc:DecisionShape ] .

# ─── Action (filesystem / network / process) ─────────────────────────

jc:ActionShape a sh:NodeShape ;
    sh:targetClass jc:Action ;
    sh:property [ sh:path jc:kind ; sh:nodeKind sh:IRI ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:FsAction jc:NetAction jc:ProcAction ) ] .

jc:FsActionShape a sh:NodeShape ;
    sh:targetClass jc:FsAction ;
    sh:property [ sh:path jc:path   ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:fsMode ; sh:nodeKind sh:IRI     ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:FsRead jc:FsWrite jc:FsExecute jc:FsList ) ] .

jc:NetActionShape a sh:NodeShape ;
    sh:targetClass jc:NetAction ;
    sh:property [ sh:path jc:host      ; sh:datatype xsd:string             ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:port      ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:minInclusive 0 ; sh:maxInclusive 65535 ] ;
    sh:property [ sh:path jc:netMethod ; sh:nodeKind sh:IRI                 ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:NetConnect jc:NetListen jc:NetResolve ) ] .

jc:ProcActionShape a sh:NodeShape ;
    sh:targetClass jc:ProcAction ;
    sh:property [ sh:path jc:binary ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:argv   ; sh:nodeKind sh:Literal ] .

# ─── Decision (Allow / Deny) ─────────────────────────────────────────

jc:DecisionShape a sh:NodeShape ;
    sh:targetClass jc:Decision ;
    sh:property [ sh:path jc:kind ; sh:nodeKind sh:IRI ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:Allow jc:Deny ) ] .

jc:AllowShape a sh:NodeShape ;
    sh:targetClass jc:Allow ;
    sh:property [ sh:path jc:rule ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] .

jc:DenyShape a sh:NodeShape ;
    sh:targetClass jc:Deny ;
    sh:property [ sh:path jc:reason ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( "no_matching_allow" "explicit_deny" ) ] ;
    sh:property [ sh:path jc:rule   ; sh:datatype xsd:string ; sh:maxCount 1 ] .

# ─── Workspace Manifest (schema "workspace/1") ───────────────────────

jc:WorkspaceManifestShape a sh:NodeShape ;
    sh:targetClass jc:WorkspaceManifest ;
    sh:property [ sh:path jc:schemaId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( "workspace/1" ) ] ;
    sh:property [ sh:path jc:owner    ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:node jc:AgentIdentityShape ] ;
    sh:property [ sh:path jc:entries  ; sh:node jc:WorkspaceEntryShape ] .

jc:WorkspaceEntryShape a sh:NodeShape ;
    sh:targetClass jc:WorkspaceEntry ;
    sh:property [ sh:path jc:path        ; sh:datatype xsd:string             ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[^/].*$" ] ;
    sh:property [ sh:path jc:contentHash ; sh:datatype xsd:string             ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] ;
    sh:property [ sh:path jc:size        ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:kind        ; sh:nodeKind sh:IRI                 ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:Blob jc:Text jc:Structured ) ] .

# ─── Agent Identity (did:key + Ed25519) ──────────────────────────────

jc:AgentIdentityShape a sh:NodeShape ;
    sh:targetClass jc:AgentIdentity ;
    sh:property [ sh:path jc:handle    ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^did:key:z[1-9A-HJ-NP-Za-km-z]+$" ] ;
    sh:property [ sh:path jc:publicKey ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] .

# ─── Tool Touch + Claim Provenance ───────────────────────────────────

jc:ToolTouchShape a sh:NodeShape ;
    sh:targetClass jc:ToolTouch ;
    sh:property [ sh:path jc:toolId            ; sh:datatype xsd:string             ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:joulesMicrojoules ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:energyProvenance  ; sh:nodeKind sh:IRI                 ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:HwShunt jc:ModelBased jc:Estimator ) ] .

jc:ClaimProvenanceShape a sh:NodeShape ;
    sh:targetClass jc:ClaimProvenance ;
    sh:property [ sh:path jc:source      ; sh:nodeKind sh:IRI ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:contentHash ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] ;
    sh:property [ sh:path jc:fetchedAt   ; sh:datatype xsd:dateTime ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:trustTier   ; sh:datatype xsd:nonNegativeInteger ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:minInclusive 0 ; sh:maxInclusive 10 ] .

# ─── Validation Contract (schema "contract/1") ───────────────────────
# Planning artifact a multi-step mission is judged against. Assertions
# carry a stable id, a priority, and a check kind; features claim
# assertion ids; the verifier mechanically computes the coverage matrix.

jc:ValidationContractShape a sh:NodeShape ;
    sh:targetClass jc:ValidationContract ;
    sh:property [ sh:path jc:schemaId  ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( "contract/1" ) ] ;
    sh:property [ sh:path jc:title      ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:authoredBy ; sh:datatype xsd:string ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:assertions ; sh:node jc:AssertionShape ; sh:minCount 1 ] ;
    sh:property [ sh:path jc:features   ; sh:node jc:FeatureShape ] .

jc:AssertionShape a sh:NodeShape ;
    sh:targetClass jc:Assertion ;
    sh:property [ sh:path jc:assertionId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:title       ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:priority    ; sh:nodeKind sh:IRI     ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:MustHave jc:ShouldHave jc:NiceToHave ) ] ;
    sh:property [ sh:path jc:check       ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:node jc:AssertionCheckShape ] .

jc:AssertionCheckShape a sh:NodeShape ;
    sh:targetClass jc:AssertionCheck ;
    sh:property [ sh:path jc:kind ; sh:nodeKind sh:IRI ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( jc:ToolCheck jc:ArtifactCheck jc:CommandCheck jc:CheckerCheck ) ] .

jc:FeatureShape a sh:NodeShape ;
    sh:targetClass jc:Feature ;
    sh:property [ sh:path jc:featureId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:title     ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:claims    ; sh:datatype xsd:string ] .

jc:ContractVerdictShape a sh:NodeShape ;
    sh:targetClass jc:ContractVerdict ;
    sh:property [ sh:path jc:schemaId     ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( "verdict/1" ) ] ;
    sh:property [ sh:path jc:contractHash ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] ;
    sh:property [ sh:path jc:passed       ; sh:datatype xsd:boolean ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:summary      ; sh:datatype xsd:string  ; sh:minCount 1 ; sh:maxCount 1 ] .

# ─── Worker Handoff (schema "handoff/1") ─────────────────────────────
# Structured wire type that forces an agent to write down what
# actually happened: what got done, what was left undone, which
# commands ran with what exit codes, what issues were discovered,
# and which procedures were followed. The journal carries it as
# a HandoffRecorded event.

jc:WorkerHandoffShape a sh:NodeShape ;
    sh:targetClass jc:WorkerHandoff ;
    sh:property [ sh:path jc:schemaId  ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:in ( "handoff/1" ) ] ;
    sh:property [ sh:path jc:worker    ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:featureId ; sh:datatype xsd:string ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:closedAt  ; sh:datatype xsd:dateTime ; sh:minCount 1 ; sh:maxCount 1 ] ;
    sh:property [ sh:path jc:completed       ; sh:datatype xsd:string ] ;
    sh:property [ sh:path jc:undone          ; sh:datatype xsd:string ] ;
    sh:property [ sh:path jc:issuesFound     ; sh:datatype xsd:string ] ;
    sh:property [ sh:path jc:proceduresFollowed ; sh:datatype xsd:string ] ;
    sh:property [ sh:path jc:commands ; sh:node jc:HandoffCommandShape ] .

jc:HandoffCommandShape a sh:NodeShape ;
    sh:targetClass jc:HandoffCommand ;
    sh:property [ sh:path jc:commandHash ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
                  sh:pattern "^[a-f0-9]{64}$" ] ;
    sh:property [ sh:path jc:argv        ; sh:datatype xsd:string ] ;
    sh:property [ sh:path jc:exitCode    ; sh:datatype xsd:integer ; sh:minCount 1 ; sh:maxCount 1 ] .
