@prefix eidos: <https://eidos.software/ontology#> .
@prefix shape: <https://eidos.software/ontology/shapes#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .

# Generated from the registries in src/ by npm run ontology. Edit the source,
# not this file. These shapes validate data against the ontology; the ontology
# itself is at /ontology/eidos.ttl.

shape:FindingShape a sh:NodeShape ;
  rdfs:comment "The no-composite rule as a validation gate. Closed: a finding carrying any other property — a composite score, a total-risk field, a safety rating — fails here, which is the claim OWL's open world cannot make." ;
  sh:targetClass eidos:Finding ;
  sh:closed true ;
  sh:ignoredProperties ( rdf:type rdfs:label rdfs:comment skos:inScheme ) ;
  sh:property [ sh:path eidos:filedBy ; sh:class eidos:Review ; sh:in ( eidos:review-evidence eidos:review-attack eidos:review-market eidos:review-playbooks eidos:review-learning eidos:review-claims ) ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:filedUnderRoster ; sh:class eidos:ReviewRoster ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasRosterStatus ; sh:class eidos:RosterStatus ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:findingOfDecision ; sh:class eidos:Decision ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:scopedToVector ; sh:class eidos:MonitoredVector ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasClassification ; sh:in ( eidos:state-high-risk eidos:state-elevated eidos:state-watch eidos:state-no-match eidos:state-unscored eidos:state-unknown eidos:state-stale eidos:state-under-review ) ; sh:maxCount 1 ] .

shape:VectorFindingShape a sh:NodeShape ;
  rdfs:comment "Only vector findings classify. Both properties form one scoped classification; generic review findings do not need either." ;
  sh:targetClass eidos:VectorFinding ;
  sh:targetSubjectsOf eidos:scopedToVector, eidos:hasClassification ;
  sh:closed true ;
  sh:ignoredProperties ( rdf:type rdfs:label rdfs:comment skos:inScheme ) ;
  sh:property [ sh:path eidos:filedBy ; sh:class eidos:Review ; sh:in ( eidos:review-evidence eidos:review-attack eidos:review-market eidos:review-playbooks eidos:review-learning eidos:review-claims ) ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:filedUnderRoster ; sh:class eidos:ReviewRoster ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasRosterStatus ; sh:class eidos:RosterStatus ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:findingOfDecision ; sh:class eidos:Decision ; sh:maxCount 1 ] ;
  sh:property [
    sh:path eidos:scopedToVector ;
    sh:class eidos:MonitoredVector ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
    sh:message "A finding is scoped to exactly one monitored vector. A documented vector never classifies." ;
  ] ;
  sh:property [
    sh:path eidos:hasClassification ;
    sh:in ( eidos:state-high-risk eidos:state-elevated eidos:state-watch eidos:state-no-match eidos:state-unscored eidos:state-unknown eidos:state-stale eidos:state-under-review ) ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
    sh:message "A finding carries exactly one state from the match or withheld partitions. LOW is not a member of either." ;
  ] .

shape:MonitoredVectorShape a sh:NodeShape ;
  rdfs:comment "A monitored vector ships a detector, is run by a review, abuses exactly one component, and carries its own indicators." ;
  sh:targetClass eidos:MonitoredVector ;
  sh:property [ sh:path eidos:hasDetector ; sh:class eidos:Detector ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:exploitsComponent ; sh:class eidos:MechanismComponent ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:runBy ; sh:class eidos:Review ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasIndicator ; sh:class eidos:Indicator ; sh:minCount 1 ] .

shape:DocumentedVectorShape a sh:NodeShape ;
  rdfs:comment "A documented vector is a definition. It has no detector, so it never assessed anything." ;
  sh:targetClass eidos:DocumentedVector ;
  sh:property [
    sh:path eidos:hasDetector ;
    sh:maxCount 0 ;
    sh:message "A documented vector has no detector: it is never assessed and never classifies." ;
  ] ;
  sh:property [ sh:path eidos:exploitsComponent ; sh:class eidos:MechanismComponent ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasIndicator ; sh:class eidos:Indicator ; sh:minCount 1 ] .

shape:ReviewShape a sh:NodeShape ;
  rdfs:comment "One review of the roster: versioned, and carrying the boundary rules it refuses to cross." ;
  sh:targetClass eidos:Review ;
  sh:property [ sh:path eidos:version ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:boundaryRule ; sh:datatype xsd:string ; sh:minCount 1 ] ;
  sh:property [ sh:path eidos:contractInputs ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:contractOutputs ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:contractHandoff ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] .

shape:McpToolShape a sh:NodeShape ;
  rdfs:comment "A review tool reads out exactly one review; an inventory tool carries none." ;
  sh:targetClass eidos:McpTool ;
  sh:property [ sh:path eidos:servesReview ; sh:class eidos:Review ; sh:in ( eidos:review-evidence eidos:review-attack eidos:review-market eidos:review-playbooks eidos:review-learning eidos:review-claims ) ; sh:maxCount 1 ] .

shape:McpResourceShape a sh:NodeShape ;
  rdfs:comment "A served document is identified by the URL it actually publishes at." ;
  sh:targetClass eidos:McpResource ;
  sh:property [ sh:path eidos:uri ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:mimeType ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] .

shape:CovenantCheckShape a sh:NodeShape ;
  rdfs:comment "A versioned check anchored to a published launch covenant." ;
  sh:targetClass eidos:CovenantCheck ;
  sh:property [ sh:path eidos:version ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:checksCovenant ; sh:class eidos:LaunchCovenant ; sh:minCount 1 ; sh:maxCount 1 ] .

shape:InstrumentShape a sh:NodeShape ;
  rdfs:comment "An observation instrument belongs to one review. Its output is an observation, never a classification." ;
  sh:targetClass eidos:Instrument ;
  sh:property [ sh:path eidos:instrumentOf ; sh:class eidos:Review ; sh:minCount 1 ; sh:maxCount 1 ] .

shape:VenueShape a sh:NodeShape ;
  rdfs:comment "A venue is one deployment on one chain, named by its operator; where an engine runs it as its own, it says which." ;
  sh:targetClass eidos:Venue ;
  sh:property [ sh:path eidos:venueOnChain ; sh:class eidos:Chain ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:venueOperator ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:ownVenueOf ; sh:class eidos:DecisionMarketEngine ; sh:maxCount 1 ] .

shape:DisprovenDerivationShape a sh:NodeShape ;
  rdfs:comment "A refusal is a record: every closed derivation states the measurement that closed it and the provenance it refuses, and a scope names a registered series." ;
  sh:targetClass eidos:DisprovenDerivation ;
  sh:property [ sh:path eidos:note ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ; sh:message "A disproven derivation states the measurement that closed it." ] ;
  sh:property [ sh:path eidos:provenancePattern ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:disprovenBefore ; sh:datatype xsd:dateTime ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:disprovenFrom ; sh:datatype xsd:dateTime ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:disprovenSignature ; sh:datatype xsd:string ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:scopedToSeries ; sh:in ( "price-usd" "market-cap-usd" "fdv-usd" "volume-24h-usd" "provider-change-24h-pct" "circulating-supply" "total-supply" "largest-holder-pct" "top-10-holders-pct" "tracked-organization-count" "live-organization-count" "cited-treasury-usd" "quoted-market-cap-usd" "launched-organization-count" "launched-organization-market-cap-usd" "launched-organization-fdv-usd" "dao-vault-usd" "pending-market-count" "funded-draft-count" "program-proposal-count" "dao-vault-balance-usd" "final-pass-twap" "final-fail-twap" "threshold-pct" "pass-twap" "fail-twap" "pass-spot" "fail-spot" "pass-base-reserve" "pass-quote-reserve" "fail-base-reserve" "fail-quote-reserve" "option-twap" "option-spot" ) ; sh:message "A scope names a series the registry records." ] ;
  sh:property [ sh:path eidos:scopedToMarket ; sh:datatype xsd:string ; sh:maxCount 1 ] .

shape:ActionTypeShape a sh:NodeShape ;
  rdfs:comment "A public verb edits one object type, states its effect, authority and preconditions, and is submitted by an external party only; the private verbs live in the workflow vocabulary." ;
  sh:targetClass eidos:ActionType ;
  sh:property [ sh:path eidos:editsObjectType ; sh:class eidos:ObjectType ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:actionVersion ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:effect ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:actionAuthority ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:criteria ; sh:datatype xsd:string ; sh:minCount 1 ] ;
  sh:property [ sh:path eidos:actorClasses ; sh:in ( "external" ) ; sh:minCount 1 ; sh:message "A public action is submitted by an external party; any other actor's verb is private." ] .

shape:DecisionShape a sh:NodeShape ;
  rdfs:comment "A decision names one engine and one chain, and its parts are the classes they say they are." ;
  sh:targetClass eidos:Decision ;
  sh:property [ sh:path eidos:onEngine ; sh:class eidos:DecisionMarketEngine ; sh:minCount 1 ; sh:maxCount 1 ; sh:message "A decision is made on exactly one engine." ] ;
  sh:property [ sh:path eidos:onChain ; sh:class eidos:Chain ; sh:minCount 1 ; sh:maxCount 1 ; sh:message "A decision runs on exactly one chain." ] ;
  sh:property [ sh:path eidos:onVenue ; sh:class eidos:Venue ] ;
  sh:property [ sh:path eidos:decisionForOrganization ; sh:class eidos:Organization ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasOption ; sh:class eidos:DecisionOption ] ;
  sh:property [ sh:path eidos:selectedOption ; sh:class eidos:DecisionOption ] ;
  sh:property [ sh:path eidos:hasPurpose ; sh:class eidos:Purpose ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:hasInformationState ; sh:class eidos:InformationState ] ;
  sh:property [ sh:path eidos:hasExecution ; sh:class eidos:Execution ] ;
  sh:property [ sh:path eidos:hasOutcomeRecord ; sh:class eidos:OutcomeRecord ] ;
  sh:property [ sh:path eidos:hasImpactRecord ; sh:class eidos:ImpactRecord ] ;
  sh:property [ sh:path eidos:hasOutcome ; sh:class eidos:MeasuredOutcome ] ;
  sh:property [ sh:path eidos:hasImpact ; sh:class eidos:Impact ] ;
  sh:property [ sh:path eidos:actedBy ; sh:class eidos:Party ] ;
  sh:property [ sh:path eidos:authorizedBy ; sh:class eidos:Authority ] .
shape:MeasuredOutcomeShape a sh:NodeShape ;
  sh:targetClass eidos:MeasuredOutcome ;
  sh:property [ sh:path eidos:outcomeValue ; sh:datatype xsd:double ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:outcomeUnit ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:outcomeSource ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:outcomeAt ; sh:datatype xsd:dateTime ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:outcomeBound ; sh:datatype xsd:string ; sh:minCount 0 ; sh:maxCount 1 ] .

shape:ImpactShape a sh:NodeShape ;
  sh:targetClass eidos:Impact ;
  sh:property [ sh:path eidos:impactOfOutcome ; sh:class eidos:MeasuredOutcome ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:impactBaseline ; sh:class eidos:MeasuredOutcome ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:impactOfRecord ; sh:class eidos:ImpactRecord ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:impactChangePct ; sh:datatype xsd:double ; sh:minCount 1 ; sh:maxCount 1 ] .

shape:OutcomeRecordShape a sh:NodeShape ;
  sh:targetClass eidos:OutcomeRecord ;
  sh:property [ sh:path eidos:recordStatus ; sh:datatype xsd:string ; sh:in ( "recorded" "withheld" ) ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:recordCheckpoint ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:recordWithheldReason ; sh:datatype xsd:string ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:recordedOutcome ; sh:class eidos:MeasuredOutcome ; sh:minCount 0 ; sh:maxCount 1 ] .

shape:ImpactRecordShape a sh:NodeShape ;
  sh:targetClass eidos:ImpactRecord ;
  sh:property [ sh:path eidos:comparisonStatus ; sh:datatype xsd:string ; sh:in ( "recorded" "withheld" ) ; sh:minCount 1 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:comparisonCheckpoint ; sh:datatype xsd:string ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:comparisonWithheldReason ; sh:datatype xsd:string ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:comparisonForecastPct ; sh:datatype xsd:double ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:comparisonSource ; sh:datatype xsd:string ; sh:minCount 0 ; sh:maxCount 1 ] ;
  sh:property [ sh:path eidos:recordedImpact ; sh:class eidos:Impact ; sh:minCount 0 ; sh:maxCount 1 ] .
