tbox: v2.2 - polymorphisme declare sur 19 proprietes, 17 domaines poses, provenance portee par les classes concretes, GovernanceLayerObject rattachee, affectations de gouvernance completes (12 completees, 10 SDO, 1 PO, 16 stewards par objet metier), Panel Coverage gouverne. Validation SHACL sans violation bloquante

This commit is contained in:
Bastien Gourdon
2026-08-07 10:31:16 +02:00
parent d90d2a316d
commit 0b7d3834d2
29 changed files with 3274 additions and 274 deletions
+14 -13
View File
@@ -1,6 +1,6 @@
# Pernod Ricard Data MetaModel — T-Box Rulebook
**Version 1.2** — Draft for review — generated 2026-08-03
**Version 1.4** — Draft for review — generated 2026-08-03
> Generated from `rules.yaml`. Do not edit this document: edit the source and regenerate (EV-007, EV-008).
@@ -188,7 +188,7 @@ The IRI is identity. It is immutable in the RDF sense — changing one is a migr
## TN-009 — A relation begins with a verb
**Statement.** The local name of an object property begins with a verb, in lower case. Both the active form and the passive or participial form are admitted: a past participle is a verb in first position. No relation begins with a preposition or with a noun.
**Statement.** The local name of an object property begins with a verb, in lower case. Both the active form and the passive or participial form are admitted: a past participle is a verb in first position. An adverb qualifying that verb is transparent and may precede it. No relation begins with a preposition or with a noun.
| | |
|---|---|
@@ -198,12 +198,12 @@ The IRI is identity. It is immutable in the RDF sense — changing one is a migr
| Executor | `check_tbox_naming.py` |
| Procedure | _pending_ |
**Why.** A relation reads as a verb and an attribute reads as a noun. The distinction is what lets a reader tell an edge from a field without opening the declaration. The explicit clause on participial forms is required: read literally, a verb-first rule would condemn a whole family of sound relations such as computedBy, storedIn and derivedFrom.
**Why.** A relation reads as a verb and an attribute reads as a noun. The distinction is what lets a reader tell an edge from a field without opening the declaration. Two clauses are stated rather than left implicit, because a literal reading would condemn sound relations: the participial one, which covers a whole family such as computedBy, storedIn and derivedFrom, and the adverbial one, which covers a relation whose verb is qualified rather than replaced.
| From | To | Note |
|---|---|---|
| pr:inDatabase | pr:isInDatabase | a preposition is not a verb |
| pr:primaryLocation | pr:primarilyStoredIn | a noun is not a verb |
| pr:primaryLocation | pr:primarilyStoredIn | a noun is not a verb; the adverb is transparent and the verb follows |
| pr:computedBy | pr:computedBy | participial form is conforming |
## TN-010 — The is prefix is either a copula or a predicate
@@ -507,7 +507,7 @@ Nothing is left to be guessed. What a term is, what it applies to, where it sits
## TN-025 — Every property declares its domain and range
**Statement.** rdfs:domain and rdfs:range are mandatory on every property, EXCEPT where the property is deliberately polymorphic. A polymorphic property states so in its comment and has its scope declared in SHACL. Silent absence is a violation; documented absence is not.
**Statement.** rdfs:domain and rdfs:range are mandatory on every property, EXCEPT where the property is deliberately polymorphic. A polymorphic property declares pr:polymorphic true and has its scope declared in SHACL. Silent absence is a violation; declared absence is not.
| | |
|---|---|
@@ -517,30 +517,31 @@ Nothing is left to be guessed. What a term is, what it applies to, where it sits
| Executor | `check_tbox_naming.py` |
| Procedure | _pending_ |
**Why.** A property with no domain cannot be targeted by any control. But some properties are polymorphic by design, their scope controlled class by class in SHACL rather than by twin properties; giving those an rdfs:domain would trigger the RDFS retyping described in TN-028. The rule therefore separates the two cases rather than demanding a domain everywhere.
**Why.** A property with no domain cannot be targeted by any control. But some properties are polymorphic by design, their scope controlled class by class in SHACL rather than by twin properties; giving those an rdfs:domain would trigger the RDFS retyping described in TN-028. The rule therefore separates the two cases rather than demanding a domain everywhere. The distinction is carried by an axiom and not by a sentence in the comment: a checker looking for a phrase in prose fails the moment someone words it differently, and what matters is declared rather than read, exactly as for abstractness.
| From | To | Note |
|---|---|---|
| a polymorphic property with no domain and no comment | violation | silence is indistinguishable from omission |
| a polymorphic property with no domain | conforming | scope declared in SHACL |
| a property with no domain and no declaration | violation | silence is indistinguishable from omission |
| a property with no domain, declaring pr:polymorphic true | conforming | scope declared in SHACL |
## TN-026 — Every term declares how it was authored
## TN-026 — Every concrete class declares how its instances are produced
**Statement.** pr:authoringMode is mandatory on every term. pr:harvestSource is mandatory if and only if the mode is HARVESTED.
**Statement.** Every CONCRETE CLASS declares pr:authoringMode, stating whether its instances are ASSERTED by governance or HARVESTED from a system. pr:harvestSource is mandatory if and only if the mode is HARVESTED. The declared mode agrees with the provenance axis the class descends from: a class under CapturedObject declares HARVESTED, one under DefinedObject declares ASSERTED. Nothing else carries the property: not an abstract class, not a property, not a term of the vocabulary in its own right.
| | |
|---|---|
| Severity | **BLOCKING** |
| Applies to | class, object_property, datatype_property, annotation_property |
| Applies to | class |
| Enforced at | script |
| Executor | `check_tbox_naming.py` |
| Procedure | _pending_ |
**Why.** Provenance decides who may edit a term and what a divergence means. A term stating where its data comes from without stating that it is harvested, or declaring itself harvested without naming a source, is half-declared in a way no control can catch. Declared symmetrically, provenance also makes a harvester specifiable from the model itself rather than from a side document.
**Why.** A term of the vocabulary is declared, always and by definition; recording that on every term would repeat one fact a hundred times and say nothing. It is the INSTANCES that have a provenance, and the class is where the model states which one: a governance object is asserted by a domain, a physical column is harvested from a system. The distinction matters because a class can be declared and describe captured things at once — CapturedObject itself is a declared term naming harvested instances, and conflating the two is what once put a harvesting mode on an abstraction. Nothing is inherited. A subclass declares its own mode rather than taking its parent's, so that the declaration is read where the instances are typed and not chased up a chain. The agreement clause is what keeps that free of contradiction: the axis says what kind of thing the class describes, the mode says how those things arrive, and a class under CapturedObject declaring ASSERTED is stating both at once. Declared this way, provenance also makes a harvester specifiable from the model itself rather than from a side document.
| From | To | Note |
|---|---|---|
| harvestSource present | authoringMode HARVESTED | |
| authoringMode on an abstract class | nothing | an abstraction has no instances to produce |
| a class under CapturedObject declaring ASSERTED | violation | the mode contradicts the axis |
| authoringMode HARVESTED, harvestSource absent | harvestSource declared | |
## TN-027 — A concrete class has one layer and one provenance