PREFIX atom:    <http://lv2plug.in/ns/ext/atom#>
PREFIX aufx:    <https://w3id.org/aufx/ontology/1.0#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX doap:    <http://usefulinc.com/ns/doap#>
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
PREFIX lv2:     <http://lv2plug.in/ns/lv2core#>
PREFIX midi:    <http://lv2plug.in/ns/ext/midi#>
PREFIX mo:      <http://purl.org/ontology/mo/>
PREFIX owl:     <http://www.w3.org/2002/07/owl#>
PREFIX prov:    <http://www.w3.org/ns/prov#>
PREFIX pu:      <http://purl.org/stuff/plugin-universe/>
PREFIX rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:    <http://www.w3.org/2000/01/rdf-schema#>
PREFIX schema:  <https://schema.org/>
PREFIX sh:      <http://www.w3.org/ns/shacl#>
PREFIX skos:    <http://www.w3.org/2004/02/skos/core#>
PREFIX spdx:    <http://spdx.org/rdf/terms#>
PREFIX studio:  <http://purl.org/ontology/studio/main/>
PREFIX time:    <http://lv2plug.in/ns/ext/time#>
PREFIX trn:     <http://purl.org/stuff/transmissions/>
PREFIX ui:      <http://lv2plug.in/ns/extensions/ui#>
PREFIX units:   <http://lv2plug.in/ns/extensions/units#>
PREFIX void:    <http://rdfs.org/ns/void#>
PREFIX xsd:     <http://www.w3.org/2001/XMLSchema#>

pu:strictness  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "The strictness level a validator was run at, 1-10 for pluginval. A condition of the measurement rather than a result of it, and recorded on every reading because \"passed pluginval\" is not a fact until it says at what level.";
        rdfs:domain   pu:Measurement;
        rdfs:range    xsd:integer .

pu:OpenTimeWarm  rdf:type  pu:Metric;
        rdfs:comment  "Time to instantiate the plugin again immediately afterwards. Where it is far below the cold figure the cost was loading the binary; where it is not, the plugin does that work every time.";
        rdfs:label    "Open time (warm)";
        units:unit    units:ms .

pu:OpenTimeCold  rdf:type  pu:Metric;
        rdfs:comment  "Time to instantiate the plugin the first time, when nothing of it is cached. This is what a user waits for when a session loads.";
        rdfs:label    "Open time (cold)";
        units:unit    units:ms .

pu:FailedTests  rdf:type  pu:Metric;
        rdfs:comment  "How many of a validator's own tests reported a failure, out of those it ran. Meaningless without pu:strictness: the same plugin fails a different number of tests at level 5 and level 10, because they are not the same tests.";
        rdfs:label    "Failed tests" .

pu:endsAt  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Promotion;
        rdfs:range   xsd:dateTime .

pu:startedAt  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Promotion;
        rdfs:range   xsd:dateTime .

pu:paidBy  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:Promotion .

pu:promotes  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:Promotion .

pu:Promotion  rdf:type  owl:Class;
        rdfs:comment  "A paid placement. Disclosed publicly: who paid, for what, and when.";
        rdfs:label    "Promotion" .

pu:composedTextHash  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Hash of the text that was embedded, so a stale embedding is detectable without re-embedding.";
        rdfs:range    xsd:string .

pu:embeddedAtTime  rdf:type  owl:DatatypeProperty;
        rdfs:range  xsd:dateTime .

pu:embeddingDimension
        rdf:type    owl:DatatypeProperty;
        rdfs:range  xsd:integer .

pu:embeddingModel  rdf:type  owl:DatatypeProperty;
        rdfs:range  xsd:string .

pu:pluginVersion  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Measurement;
        rdfs:range   xsd:string .

pu:blockSize  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Measurement;
        rdfs:range   xsd:integer .

pu:sampleRate  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Measurement;
        rdfs:range   xsd:integer .

pu:platform  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Measurement;
        rdfs:range   xsd:string .

pu:tool  rdf:type     owl:DatatypeProperty;
        rdfs:comment  "Tool and version, e.g. 'pluginval 1.0.3'.";
        rdfs:domain   pu:Measurement;
        rdfs:range    xsd:string .

pu:value  rdf:type   owl:DatatypeProperty;
        rdfs:domain  pu:Measurement .

pu:metric  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:Measurement;
        rdfs:range   pu:Metric .

pu:subject  rdf:type  owl:ObjectProperty;
        rdfs:comment  "The plugin measured.";
        rdfs:domain   pu:Measurement .

pu:StateIntegrity  rdf:type  pu:Metric;
        rdfs:label  "State save/restore integrity" .

pu:signal  rdf:type   owl:DatatypeProperty;
        rdfs:comment  "The signal a crashing scan died from, where it died from one. A plugin that takes the scanning tool with it is a recorded result.";
        rdfs:domain   pu:Measurement;
        rdfs:range    xsd:string .

pu:DiscoveredPorts  rdf:type  pu:Metric;
        rdfs:comment  "Ports the built binary reports through lilv, which is what a host sees. Comparing it with the harvested profile's count is how a disagreement between a bundle's Turtle and its binary becomes visible.";
        rdfs:label    "Discovered ports" .

pu:DiscoveredControlPorts
        rdf:type      pu:Metric;
        rdfs:comment  "Control ports the built binary reports — the like-for-like counterpart of the parameter count in a harvested profile. Comparing the profile against the *total* port count instead makes every plugin look wrong, because a binary also has audio and atom ports.";
        rdfs:label    "Discovered control ports" .

pu:DenormalBehaviour  rdf:type  pu:Metric;
        rdfs:label  "Denormal behaviour" .

pu:ValidationResult  rdf:type  pu:Metric;
        rdfs:comment  "Verdict from a format validator. 'passed' and 'failed' are pluginval's own conclusions about the plugin; 'crashed' and 'timed-out' are what the sandbox saw; 'unloadable' means the profiler image could not load the binary at all and says nothing about the plugin. They are kept distinct on purpose — a plugin that fails a test and a plugin that killed the validator are different facts about it, and a plugin the profiler is too old to load is a fact about the profiler.";
        rdfs:label    "Validation result" .

pu:ScanTime  rdf:type  pu:Metric;
        rdfs:comment  "Time to enumerate the plugin.";
        rdfs:label    "Scan time";
        units:unit    units:ms .

pu:LatencySamples  rdf:type  pu:Metric;
        rdfs:comment  "Latency in samples, as reported by the plugin while running. Needs a host that actually instantiates it and asks, which is pluginval; pu:Latency is the scan-time counterpart that only says whether latency is declared at all.";
        rdfs:label    "Latency";
        units:unit    units:frame .

pu:Latency  rdf:type  pu:Metric;
        rdfs:comment  "Whether the plugin declares latency to its host. Boolean, because this is what a scan can establish: a static scan sees that a latency port exists, not what the plugin reports through it at run time.";
        rdfs:label    "Reports latency";
        rdfs:seeAlso  pu:LatencySamples .

pu:CpuLoad  rdf:type  pu:Metric;
        rdfs:comment  "Percentage of one core consumed at the stated block size and sample rate.";
        rdfs:label    "CPU load";
        units:unit    units:pc .

pu:Metric  rdf:type  owl:Class;
        rdfs:label  "Metric" .

pu:Measurement  rdf:type  owl:Class;
        rdfs:comment  "One observation produced by a profiler run.";
        rdfs:label    "Measurement" .

pu:editSummary  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "What changed and why, in the contributor's words. Optional, and about the edit rather than about the plugin.";
        rdfs:domain   pu:WikiRevision;
        rdfs:range    xsd:string .

pu:wikiText  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Markdown as the contributor typed it. The source is stored and never the rendered HTML: rendering is a decision made on the way out, so a change to how prose is sanitised applies to every revision ever written rather than only to the next one.";
        rdfs:domain   pu:WikiRevision;
        rdfs:range    xsd:string .

pu:wikiSubject  rdf:type  owl:ObjectProperty;
        rdfs:comment  "The plugin this revision is about. Not pu:subject, whose domain is pu:Measurement — a measurement and a paragraph are about a plugin in different senses and conflating the properties would make either query wrong.";
        rdfs:domain   pu:WikiRevision .

pu:WikiRevision  rdf:type  owl:Class;
        rdfs:comment  "One saved version of the prose about a plugin. Revisions are never edited and never deleted: saving writes a new one that supersedes the last through prov:wasRevisionOf, so the history is the data rather than a log kept beside it. That is also what makes a bad edit reversible without trusting anybody's backup.";
        rdfs:label    "Wiki revision" .

pu:reviewedAt  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:Correction;
        rdfs:range   xsd:dateTime .

pu:reviewedBy  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:Correction .

pu:correctionStatus  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "pending, accepted or rejected. A correction from a trusted contributor is accepted on arrival; one from a new contributor waits.";
        rdfs:domain   pu:Correction;
        rdfs:range    xsd:string .

pu:rationale  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Why. Free text, and the only part of a correction that is authored prose rather than a fact — but it is about the contribution rather than about the plugin, so it stays with the correction in the system graph.";
        rdfs:domain   pu:Correction;
        rdfs:range    xsd:string .

pu:currentValue  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "What it said when the correction was made. Kept so a reviewer can see whether the catalogue changed underneath the proposal.";
        rdfs:domain   pu:Correction .

pu:proposedValue  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "What the contributor says it should be.";
        rdfs:domain   pu:Correction .

pu:correctionPredicate
        rdf:type      owl:DatatypeProperty;
        rdfs:comment  "Which property is being corrected, as an IRI string. Restricted to a whitelist: a correction is not a way to write arbitrary triples.";
        rdfs:domain   pu:Correction;
        rdfs:range    xsd:string .

pu:correctionSubject  rdf:type  owl:ObjectProperty;
        rdfs:comment  "The plugin the correction is about.";
        rdfs:domain   pu:Correction .

pu:Correction  rdf:type  owl:Class;
        rdfs:comment  "A proposed change to one statement about one plugin. Typed rather than free text, so it can be validated against the shapes before it is written and applied mechanically once accepted.";
        rdfs:label    "Correction" .

pu:Paid  rdf:type   pu:Pricing;
        rdfs:label  "Paid" .

pu:Freemium  rdf:type  pu:Pricing;
        rdfs:comment  "A free tier alongside a paid one.";
        rdfs:label    "Freemium" .

pu:Pricing  rdf:type  owl:Class;
        rdfs:label  "Pricing" .

pu:Proprietary  rdf:type  pu:SourceAvailability;
        rdfs:comment  "No source. Asserted only where a source says so; an absent licence means unknown, not proprietary.";
        rdfs:label    "Proprietary" .

pu:SourceAvailable  rdf:type  pu:SourceAvailability;
        rdfs:comment  "Source can be read but the licence does not grant the freedoms of an open-source one.";
        rdfs:label    "Source available" .

pu:SourceAvailability
        rdf:type    owl:Class;
        rdfs:label  "Source Availability" .

pu:     rdf:type         owl:Ontology;
        rdfs:comment     "Terms for the Plugin Universe catalogue that have no home in an existing vocabulary. Plugin description proper uses trn: for curated behaviour and lv2:/units: for parameters; this covers measurement, packaging and catalogue administration.";
        rdfs:label       "Plugin Universe vocabulary";
        dcterms:license  <https://creativecommons.org/publicdomain/zero/1.0/> .

pu:suspended  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Checked against the account on every request rather than carried in the session cookie, so suspension takes effect immediately even though sessions are stateless.";
        rdfs:range    xsd:boolean .

pu:tier  rdf:type     owl:DatatypeProperty;
        rdfs:comment  "registered, pro or admin.";
        rdfs:range    xsd:string .

pu:trustLevel  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "new, trusted or moderator. Earned, never asserted by the account holder: it decides whether a contribution is queued or goes live.";
        rdfs:range    xsd:string .

pu:lastSeen  rdf:type  owl:DatatypeProperty;
        rdfs:range  xsd:dateTime .

pu:githubId  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "The GitHub numeric id. Identity is minted from this rather than the login, because a login can be renamed and an account whose IRI moved would orphan every contribution attributed to it.";
        rdfs:range    xsd:string .

pu:Donationware  rdf:type  pu:Pricing;
        rdfs:label  "Donationware" .

pu:Free  rdf:type   pu:Pricing;
        rdfs:label  "Free" .

pu:pricing  rdf:type  owl:ObjectProperty;
        rdfs:comment  "Never derived from a licence: an open-source licence grants the right to the source, not a free binary. Asserted only by a harvester whose source states it, and carrying that source's provenance.";
        rdfs:range    pu:Pricing .

pu:OpenSource  rdf:type  pu:SourceAvailability;
        rdfs:comment  "Released under an OSI-approved licence or a public-domain dedication. Derived from the stated licence, never guessed.";
        rdfs:label    "Open source" .

pu:sourceAvailability
        rdf:type      owl:ObjectProperty;
        rdfs:comment  "Derived from the plugin's own licence. Absent means unknown.";
        rdfs:range    pu:SourceAvailability .

pu:licenceId  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "The plugin's licence as an SPDX identifier where one is recognisable. dcterms:license keeps whatever the source actually said.";
        rdfs:range    xsd:string .

pu:donateUrl  rdf:type  owl:DatatypeProperty;
        rdfs:range  xsd:anyURI .

pu:audioPreview  rdf:type  owl:DatatypeProperty;
        rdfs:range  xsd:anyURI .

pu:attested  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "A build artifact attestation exists for this file. Computed at harvest.";
        rdfs:range    xsd:boolean .

pu:containsArtefact  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "A payload kind the registry names that is not a plugin format — a raw binary or a standalone executable. Kept verbatim rather than guessed at: a bare 'dll' does not say which plugin API it implements.";
        rdfs:domain   pu:PackageFile;
        rdfs:range    xsd:string .

pu:operatingSystem  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   xsd:string .

pu:architecture  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   xsd:string .

pu:containsFormat  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   trn:PluginFormat .

pu:fileKind  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "archive or installer.";
        rdfs:domain   pu:PackageFile;
        rdfs:range    xsd:string .

pu:fileSize  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   xsd:integer .

pu:sha256  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   xsd:string .

pu:downloadUrl  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:PackageFile;
        rdfs:range   xsd:anyURI .

pu:PackageFile  rdf:type  owl:Class;
        rdfs:comment  "One downloadable artefact of a package version.";
        rdfs:label    "Package File" .

pu:packageFile  rdf:type  owl:ObjectProperty;
        rdfs:domain  pu:Package;
        rdfs:range   pu:PackageFile .

pu:packageVersion  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Semantic version as the registry states it.";
        rdfs:domain   pu:Package;
        rdfs:range    xsd:string .

pu:Package  rdf:type  owl:Class;
        rdfs:comment  "A distributable release of a plugin, preset, project or app.";
        rdfs:label    "Package" .

pu:package  rdf:type  owl:ObjectProperty;
        rdfs:comment  "A released package of this plugin.";
        rdfs:range    pu:Package .

pu:tag  rdf:type      owl:DatatypeProperty;
        rdfs:comment  "A source's own keyword, unmapped and unmodified. Feeds retrieval; carries no semantics.";
        rdfs:range    xsd:string .

pu:verified  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "The package slug's organisation matches the download URL's domain. Computed at harvest, never asserted by a submitter.";
        rdfs:range    xsd:boolean .

pu:downloadCount  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Downloads reported by the source at harvest time. A snapshot, not a fact about the plugin.";
        rdfs:range    xsd:integer .

pu:slug  rdf:type     owl:DatatypeProperty;
        rdfs:comment  "Registry identifier in organisation/package-name form.";
        rdfs:range    xsd:string .

pu:unitLabel  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "A parameter's unit as the source wrote it, kept when it could not be mapped to a units: individual. Losing the label would be worse than failing to type it.";
        rdfs:range    xsd:string .

pu:category  rdf:type  owl:ObjectProperty;
        rdfs:comment  "A concept from the catalogue's category scheme. Source categories, LV2 plugin classes and user tags map in as skos:closeMatch.";
        rdfs:range    skos:Concept .

pu:harvestRun  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:SourceGraph;
        rdfs:range   xsd:string .

pu:precedence  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Source precedence for conflict resolution. Higher wins.";
        rdfs:domain   pu:SourceGraph;
        rdfs:range    xsd:integer .

pu:inCC0Dump  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Whether this graph may appear in the CC0 dataset dump without an attached notice.";
        rdfs:domain   pu:SourceGraph;
        rdfs:range    xsd:boolean .

pu:redistributable  rdf:type  owl:DatatypeProperty;
        rdfs:comment  "Whether this graph's content may be published at all.";
        rdfs:domain   pu:SourceGraph;
        rdfs:range    xsd:boolean .

pu:graphKind  rdf:type  owl:DatatypeProperty;
        rdfs:domain  pu:SourceGraph;
        rdfs:range   xsd:string .

pu:SourceGraph  rdf:type  owl:Class;
        rdfs:comment  "A named graph holding data from one source, carrying its provenance and licence. Every triple in the catalogue lives in one of these.";
        rdfs:label    "Source Graph" .
