tbox: v1.6 - provenance portee par les classes concretes, isAbstract declare et non plus infere, ForeignKeyConstraint devient ForeignKey, les dix classes sans rdfs:comment completees

This commit is contained in:
Bastien Gourdon
2026-08-05 09:13:12 +02:00
parent f83b7d7491
commit 1c8ab77003
20 changed files with 4770 additions and 1081 deletions
+591
View File
@@ -0,0 +1,591 @@
# Pernod Ricard Data MetaModel — T-Box Processbook
**Version 0.1** — Draft for review — generated 2026-08-03
> Generated from `processes.yaml`. The BPMN files in `bpmn/` are the authoritative form; the views below are derived from the same source. Do not edit this document (EV-007, EV-008).
Procedures for changing the vocabulary of the model. Each procedure names the rules it enforces, the steps a person must perform, and the points at which the work stops rather than continues.
## Procedures
| Id | Family | Procedure | Scope |
|---|---|---|---|
| **X1** | Release | Propagate a change and publish a version | Any validated modification of the vocabulary. |
| **C1** | Create | Create a term | class | relation | attribute | annotation |
| **C2** | Create | Create a controlled value | typed individual | literal |
| **C3** | Create | Create a shape | Any SHACL constraint added to the validation set. |
| **D1** | Delete | Deprecate a term | class | relation | attribute | annotation | individual |
| **D2** | Delete | Withdraw a term permanently | class | relation | attribute | annotation | individual |
| **R1** | Verify | Verify the vocabulary against the rulebook | The whole vocabulary, or the subset touched by a change. |
| **R2** | Verify | Validate instances against the shapes | Any instance graph in the validation perimeter. |
| **R3** | Verify | Audit what the shapes cannot see | The whole vocabulary and its source file. |
## Reading a diagram
- A **rounded** node is a start or end state.
- A **diamond** is a decision; every outgoing path is labelled.
- A **shaded** box is a human task: it cannot be automated, and the work stops there until someone acts.
- A **double-bordered** box calls another procedure by its identifier.
---
# X1 — Propagate a change and publish a version
| | |
|---|---|
| Family | Release |
| Scope | Any validated modification of the vocabulary. |
| Trigger | A change to the vocabulary has been agreed and is ready to apply. |
| Inputs | the agreed change, the target version, the list of affected artifacts |
| Outputs | a merged branch, a tagged version, an execution log |
| Rules enforced | EV-004, EV-005, EV-006, EV-007, EV-008, EV-009, EV-010, EV-014, EV-015, TN-023 |
| Calls | R1, R2 |
**Note.** The most frequently invoked procedure of the processbook: every other procedure ends by calling it. Two of its steps are gateways rather than checks, because an idempotence failure and a validation failure must stop the work rather than be noted in passing.
```mermaid
flowchart TD
start(["Change agreed"])
branch["Create the migration branch"]
apply["Apply the change through an RDF parser"]
labels["Regenerate labels by derivation"]
abox["Propagate to the instances"]
shapes["Update the shapes and align conformsTo"]
artifacts["Regenerate every derived artifact"]
replay["Replay the chain a second time"]
idem{"Second run reports zero change?"}
verify_voc[["R1: Verify the vocabulary"]]
verify_abox[["R2: Validate the instances"]]
log["Write the execution log for this attempt"]
clean{"Any violation?"}
decide["Correct or abandon"]
drop["Destroy the branch and restart from the published version"]
review["Review the merge"]
merge["Merge as a block"]
bump["Increment the ontology version"]
end(["Version published"])
aborted(["Change abandoned"])
start --> branch
branch --> apply
apply --> labels
labels --> abox
abox --> shapes
shapes --> artifacts
artifacts --> replay
replay --> idem
idem -->|zero change| verify_voc
idem -->|the chain is not replayable| decide
verify_voc --> verify_abox
verify_abox --> log
log --> clean
clean -->|none| review
clean -->|at least one| decide
decide -->|correct| apply
decide -->|abandon| drop
drop --> aborted
review --> merge
merge --> bump
bump --> end
class idem decision;
class clean decision;
class decide human;
class review human;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Create the migration branch | script | EV-009 |
| Apply the change through an RDF parser | script | EV-005, EV-006 |
| Regenerate labels by derivation | script | TN-023 |
| Propagate to the instances | script | EV-009 |
| Update the shapes and align conformsTo | script | EV-010 |
| Regenerate every derived artifact | script | EV-008 |
| Replay the chain a second time | script | EV-006, EV-007 |
| Second run reports zero change? | decision | - |
| Verify the vocabulary (R1) | calls | - |
| Validate the instances (R2) | calls | - |
| Write the execution log for this attempt | script | EV-015 |
| Any violation? | decision | - |
| Correct or abandon | human | EV-004, EV-007 |
| Destroy the branch and restart from the published version | script | EV-007 |
| Review the merge | human | EV-004, EV-009 |
| Merge as a block | script | EV-009 |
| Increment the ontology version | script | EV-014 |
---
# C1 — Create a term
| | |
|---|---|
| Family | Create |
| Scope | class | relation | attribute | annotation |
| Trigger | A missing concept, edge or field has been identified. |
| Inputs | the intended meaning, the nature, the target layer, the provenance, the parent or the domain and range |
| Outputs | a declared term, a published version |
| Rules enforced | EV-004, TN-001, TN-002, TN-003, TN-004, TN-005, TN-006, TN-007, TN-009, TN-010, TN-011, TN-012, TN-013, TN-014, TN-015, TN-018, TN-019, TN-020, TN-021, TN-022, TN-023, TN-024, TN-025, TN-026, TN-027, TN-028 |
| Calls | R1, X1 |
**Parameter.** The nature of the term selects the naming rules applied at the naming step: a class takes TN-001, TN-002, TN-004, TN-005, TN-006, TN-007 and TN-027; a relation takes TN-001, TN-002, TN-009, TN-010, TN-011 and TN-028; an attribute takes TN-001, TN-002, TN-004, TN-012, TN-013, TN-014 and TN-015; an annotation takes TN-001, TN-002 and TN-003.
**Note.** The first step has no tool today. Checking that no existing term already covers the need is the semantic uniqueness control that SHACL cannot perform, and it stays a human task until R3 exists.
```mermaid
flowchart TD
start(["Need identified"])
unique["Check that no existing term covers the need"]
exists{"A term already covers it?"}
reuse(["Reuse the existing term"])
name["Name the term according to its nature"]
label["Derive the label"]
short["Decide the short label and the acronym"]
comment["Write the comment"]
declare["Declare typing"]
validate["Validate before applying"]
check[["R1: Verify against the rulebook"]]
release[["X1: Propagate and publish"]]
end(["Term available"])
start --> unique
unique --> exists
exists -->|yes| reuse
exists -->|no| name
name --> label
label --> short
short --> comment
comment --> declare
declare --> validate
validate --> check
check --> release
release --> end
class unique human;
class exists decision;
class short human;
class comment human;
class validate human;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Check that no existing term covers the need | human | - |
| A term already covers it? | decision | - |
| Name the term according to its nature | script | TN-001, TN-002, TN-003, TN-004, TN-005, TN-006, TN-009, TN-010, TN-011, TN-012, TN-013, TN-014, TN-015, TN-028 |
| Derive the label | script | TN-018, TN-019, TN-020, TN-021, TN-023 |
| Decide the short label and the acronym | human | TN-022 |
| Write the comment | human | TN-024 |
| Declare typing | script | TN-007, TN-025, TN-026, TN-027 |
| Validate before applying | human | EV-004 |
| Verify against the rulebook (R1) | calls | - |
| Propagate and publish (X1) | calls | - |
---
# C2 — Create a controlled value
| | |
|---|---|
| Family | Create |
| Scope | typed individual | literal |
| Trigger | A new value is needed in a controlled set. |
| Inputs | the value, the set it belongs to, whether a domain may add others |
| Outputs | a declared value, a published version |
| Rules enforced | EV-004, TN-001, TN-016, TN-017, TN-018, TN-022 |
| Calls | C3, R1, X1 |
**Parameter.** The form is not a style choice but the outcome of the first decision. The two branches have different consequences: the literal branch edits the shapes and therefore the vocabulary, so it falls under the version freeze; the individual branch touches nothing else.
```mermaid
flowchart TD
start(["New value needed"])
decide["Must it be defined, owned or extended by a domain?"]
form{"Which form?"}
indiv["Create the typed individual and derive its label"]
literal["Write the literal in upper snake case"]
shape[["C3: Extend the closed list in the shapes"]]
validate["Validate before applying"]
check[["R1: Verify against the rulebook"]]
release[["X1: Propagate and publish"]]
end(["Value available"])
start --> decide
decide --> form
form -->|extensible by a domain| indiv
form -->|closed governance state| literal
indiv --> validate
literal --> shape
shape --> validate
validate --> check
check --> release
release --> end
class decide human;
class form decision;
class validate human;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Must it be defined, owned or extended by a domain? | human | TN-016 |
| Which form? | decision | - |
| Create the typed individual and derive its label | script | TN-001, TN-018, TN-022 |
| Write the literal in upper snake case | script | TN-017 |
| Extend the closed list in the shapes (C3) | calls | - |
| Validate before applying | human | EV-004 |
| Verify against the rulebook (R1) | calls | - |
| Propagate and publish (X1) | calls | - |
---
# C3 — Create a shape
| | |
|---|---|
| Family | Create |
| Scope | Any SHACL constraint added to the validation set. |
| Trigger | A rule needs an executor, or a new class enters the validation perimeter. |
| Inputs | the rule to enforce, the target class or property |
| Outputs | a shape, a rulebook entry naming it as executor |
| Rules enforced | EV-010, EV-011, EV-012, EV-013 |
| Calls | R2, X1 |
**Note.** The step that is forgotten is the last one before release: recording the shape as the executor of its rule. Without it a rule stays declared blocking with nothing enforcing it, which EV-011 forbids.
```mermaid
flowchart TD
start(["Constraint needed"])
write["Write the constraint"]
pattern["Check that every pattern is expressed positively"]
portable{"Expressible within the specification?"}
demote["Move the rule to the script tier"]
conforms["Align the declared ontology version"]
test[["R2: Test against real instances"]]
record["Record the shape as the executor of its rule"]
release[["X1: Propagate and publish"]]
end(["Shape in force"])
start --> write
write --> pattern
pattern --> portable
portable -->|yes| conforms
portable -->|no| demote
demote --> record
conforms --> test
test --> record
record --> release
release --> end
class write human;
class portable decision;
class demote human;
class record human;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Write the constraint | human | - |
| Check that every pattern is expressed positively | script | EV-013 |
| Expressible within the specification? | decision | - |
| Move the rule to the script tier | human | EV-012 |
| Align the declared ontology version | script | EV-010 |
| Test against real instances (R2) | calls | - |
| Record the shape as the executor of its rule | human | EV-011, EV-012 |
| Propagate and publish (X1) | calls | - |
---
# D1 — Deprecate a term
| | |
|---|---|
| Family | Delete |
| Scope | class | relation | attribute | annotation | individual |
| Trigger | A term is superseded or no longer needed. |
| Inputs | the term, its replacement if any |
| Outputs | a deprecated stub, a published version |
| Rules enforced | EV-001, EV-015, TN-020 |
| Calls | X1 |
**Note.** The count at step two is informative, not a condition: a term may be deprecated whether or not it is instantiated. It becomes a condition only in D2.
```mermaid
flowchart TD
start(["Term superseded"])
replacement["Identify the replacement"]
count["Count the instances for information"]
mark["Mark deprecated and declare the replacement"]
strip["Strip the stub of every edge"]
label["Remove any mention of state from the label"]
release[["X1: Propagate and publish"]]
end(["Term deprecated"])
start --> replacement
replacement --> count
count --> mark
mark --> strip
strip --> label
label --> release
release --> end
class replacement human;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Identify the replacement | human | - |
| Count the instances for information | script | EV-015 |
| Mark deprecated and declare the replacement | script | EV-001 |
| Strip the stub of every edge | script | EV-001 |
| Remove any mention of state from the label | script | TN-020 |
| Propagate and publish (X1) | calls | - |
---
# D2 — Withdraw a term permanently
| | |
|---|---|
| Family | Delete |
| Scope | class | relation | attribute | annotation | individual |
| Trigger | A deprecated term is to be removed from the vocabulary. |
| Inputs | the deprecated term |
| Outputs | a vocabulary without the term, a proof of non-instantiation, a published version |
| Rules enforced | EV-002, EV-003, EV-015 |
| Calls | R1, R2, X1 |
**Note.** The reference cleaning step is what prevents phantom nodes: a subject removed while its identifier is still cited elsewhere is reconstructed by inference, present in traversals and absent from every control. It is a step of the procedure, not a check at the end of a script.
```mermaid
flowchart TD
start(["Withdrawal requested"])
count["Run the counting query"]
instantiated{"Any instance found?"}
keep(["Kept deprecated"])
proof["Attach the proof to the commit"]
remove["Remove the subject block"]
refs["Remove every reference naming the subject"]
check_voc[["R1: Verify the vocabulary"]]
check_abox[["R2: Validate the instances"]]
release[["X1: Propagate and publish"]]
end(["Term withdrawn"])
start --> count
count --> instantiated
instantiated -->|yes| keep
instantiated -->|no| proof
proof --> remove
remove --> refs
refs --> check_voc
check_voc --> check_abox
check_abox --> release
release --> end
class instantiated decision;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Run the counting query | script | EV-002, EV-015 |
| Any instance found? | decision | - |
| Attach the proof to the commit | script | EV-002, EV-015 |
| Remove the subject block | script | - |
| Remove every reference naming the subject | script | EV-003 |
| Verify the vocabulary (R1) | calls | - |
| Validate the instances (R2) | calls | - |
| Propagate and publish (X1) | calls | - |
---
# R1 — Verify the vocabulary against the rulebook
| | |
|---|---|
| Family | Verify |
| Scope | The whole vocabulary, or the subset touched by a change. |
| Trigger | A term has been created, changed or withdrawn, or a release is prepared. |
| Inputs | the vocabulary, the rulebook source |
| Outputs | a conformance report |
| Rules enforced | EV-014, TN-001, TN-002, TN-003, TN-004, TN-005, TN-006, TN-007, TN-008, TN-009, TN-010, TN-011, TN-012, TN-013, TN-014, TN-015, TN-016, TN-017, TN-018, TN-019, TN-020, TN-021, TN-022, TN-023, TN-024, TN-025, TN-026, TN-027, TN-028 |
| Calls | - |
**Note.** Two tiers run in sequence, not in parallel: the script settles everything mechanisable, and a person answers only for the rules no script can judge. Reversing the order wastes review time on findings the script would have caught.
```mermaid
flowchart TD
start(["Verification requested"])
script["Run the naming and declaration checks"]
mechanised{"Any mechanised violation?"}
report_fail(["Report returned with violations"])
human["Review the rules no script can judge"]
judged{"Reviewer raises an issue?"}
report_ok(["Vocabulary conforms"])
start --> script
script --> mechanised
mechanised -->|at least one| report_fail
mechanised -->|none| human
human --> judged
judged -->|yes| report_fail
judged -->|no| report_ok
class mechanised decision;
class human human;
class judged decision;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Run the naming and declaration checks | script | TN-001, TN-002, TN-003, TN-004, TN-005, TN-006, TN-007, TN-009, TN-010, TN-011, TN-012, TN-013, TN-014, TN-015, TN-017, TN-018, TN-019, TN-020, TN-021, TN-023, TN-025, TN-026, TN-027, TN-028, EV-014 |
| Any mechanised violation? | decision | - |
| Review the rules no script can judge | human | TN-008, TN-016, TN-022, TN-024 |
| Reviewer raises an issue? | decision | - |
---
# R2 — Validate instances against the shapes
| | |
|---|---|
| Family | Verify |
| Scope | Any instance graph in the validation perimeter. |
| Trigger | Instances have changed, shapes have changed, or a release is prepared. |
| Inputs | the instance graph, the shapes, the ontology |
| Outputs | a validation report |
| Rules enforced | EV-010 |
| Calls | - |
**Note.** The version check comes first and aborts rather than warns. Validating against shapes that target another version of the ontology does not fail loudly: it returns a long list of violations that reads exactly like a regression of the model.
```mermaid
flowchart TD
start(["Validation requested"])
conforms["Compare the declared target version with the ontology version"]
match{"Versions match?"}
abort(["Aborted on version mismatch"])
run["Run the shape validation"]
violations{"Any violation?"}
fail(["Report returned with violations"])
ok(["Instances conform"])
start --> conforms
conforms --> match
match -->|no| abort
match -->|yes| run
run --> violations
violations -->|at least one| fail
violations -->|none| ok
class match decision;
class violations decision;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Compare the declared target version with the ontology version | script | EV-010 |
| Versions match? | decision | - |
| Run the shape validation | script | - |
| Any violation? | decision | - |
---
# R3 — Audit what the shapes cannot see
| | |
|---|---|
| Family | Verify |
| Scope | The whole vocabulary and its source file. |
| Trigger | Periodic audit, or before a version is published. |
| Inputs | the vocabulary, its source file |
| Outputs | a shortlist of suspected duplicates, a list of duplicated blocks |
| Rules enforced | EV-012 |
| Calls | - |
**Note.** Shape validation reads a graph, not a file and not meaning. Two identifiers standing for the same notion produce two individually valid graphs; a duplicated block of text produces identical triples and no complaint. This procedure is the tier those rules fall to, and its output is a shortlist for a person rather than a verdict.
```mermaid
flowchart TD
start(["Audit requested"])
index["Build the normalised label index"]
hash["Hash every normalised subject block"]
shortlist{"Any candidate found?"}
clean(["Nothing to arbitrate"])
review["Arbitrate each candidate"]
act{"Duplication confirmed?"}
merge(["Referred to the merge procedure"])
dismissed(["Candidates dismissed"])
start --> index
index --> hash
hash --> shortlist
shortlist -->|none| clean
shortlist -->|at least one| review
review --> act
act -->|yes| merge
act -->|no| dismissed
class shortlist decision;
class review human;
class act decision;
classDef human fill:#FFF4CE,stroke:#B08900;
classDef decision fill:#E8F0F7,stroke:#3E6E96;
```
| Step | Type | Rules |
|---|---|---|
| Build the normalised label index | script | EV-012 |
| Hash every normalised subject block | script | EV-012 |
| Any candidate found? | decision | - |
| Arbitrate each candidate | human | - |
| Duplication confirmed? | decision | - |
---
# Rule coverage
Which procedures enforce each rule. Derived, not maintained: a rule cited in a diagram appears here automatically.
| Rule | Procedures |
|---|---|
| EV-001 | D1 |
| EV-002 | D2 |
| EV-003 | D2 |
| EV-004 | C1, C2, X1 |
| EV-005 | X1 |
| EV-006 | X1 |
| EV-007 | X1 |
| EV-008 | X1 |
| EV-009 | X1 |
| EV-010 | C3, R2, X1 |
| EV-011 | C3 |
| EV-012 | C3, R3 |
| EV-013 | C3 |
| EV-014 | R1, X1 |
| EV-015 | D1, D2, X1 |
| TN-001 | C1, C2, R1 |
| TN-002 | C1, R1 |
| TN-003 | C1, R1 |
| TN-004 | C1, R1 |
| TN-005 | C1, R1 |
| TN-006 | C1, R1 |
| TN-007 | C1, R1 |
| TN-008 | R1 |
| TN-009 | C1, R1 |
| TN-010 | C1, R1 |
| TN-011 | C1, R1 |
| TN-012 | C1, R1 |
| TN-013 | C1, R1 |
| TN-014 | C1, R1 |
| TN-015 | C1, R1 |
| TN-016 | C2, R1 |
| TN-017 | C2, R1 |
| TN-018 | C1, C2, R1 |
| TN-019 | C1, R1 |
| TN-020 | C1, D1, R1 |
| TN-021 | C1, R1 |
| TN-022 | C1, C2, R1 |
| TN-023 | C1, R1, X1 |
| TN-024 | C1, R1 |
| TN-025 | C1, R1 |
| TN-026 | C1, R1 |
| TN-027 | C1, R1 |
| TN-028 | C1, R1 |