# 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 |