diff --git a/.opencode/rules/linkml/engineering-parsimony-and-domain-modeling-rule.md b/.opencode/rules/linkml/engineering-parsimony-and-domain-modeling-rule.md index 5ab6222aa8..64fa22b89b 100644 --- a/.opencode/rules/linkml/engineering-parsimony-and-domain-modeling-rule.md +++ b/.opencode/rules/linkml/engineering-parsimony-and-domain-modeling-rule.md @@ -2,8 +2,16 @@ ## Critical Convention -Our ontology follows an engineering-oriented approach: practical domain utility and -stable interoperability take priority over minimal, tool-specific class catalogs. +This project now has two legitimate ontology layers: + +1. An **engineering ontology** in `schemas/20251121/linkml/modules/` optimized for + operational richness, data pipelines, and implementation-ready distinctions. +2. A **parsimonious ontology** in `schemas/20251121/linkml/parsimony/` optimized for + conceptual clarity, semantic hypernyms, and dashboard-friendly overview. + +The engineering layer remains the authoritative implementation layer, but the +parsimonious layer is allowed to collapse multiple engineering classes into a +smaller conceptual facade when the downward mapping is made explicit. ## Rule @@ -23,6 +31,22 @@ stable interoperability take priority over minimal, tool-specific class catalogs 5. Avoid ontology growth driven by transient engineering stack choices. - New class proposals must be justified by cross-tool, domain-stable semantics. +6. Permit a parsimonious hypernym layer when it is explicitly bridged to the engineering layer. + - A parsimonious class may stand above multiple engineering classes. + - This semantic collapse is allowed only if the mapping to engineering classes, + slots, and enums is documented. + +7. Do not force engineering-level granularity into the parsimonious package. + - If the engineering ontology distinguishes `Custodian`, `CustodianPlace`, + `CustodianLegalStatus`, and many institutional subtypes, the parsimonious + layer may use a smaller set such as `CustodialEntity`, `PlaceContext`, and + `Reconstruction`. + +8. Treat the parsimonious layer as a semantic facade, not a replacement. + - The engineering ontology still carries implementation detail. + - The parsimonious ontology must explain that detail through mappings rather + than re-encoding the full engineering taxonomy. + ## Rationale - Tool names are volatile implementation details and age quickly. @@ -30,6 +54,9 @@ stable interoperability take priority over minimal, tool-specific class catalogs - This aligns with an engineering ontology practice where strict theoretical parsimony in candidate theories is not the only optimization criterion; practical semantic interoperability and maintainability are primary. +- A separate parsimonious layer improves conceptual navigation and UML readability + without sacrificing engineering precision, provided that cross-layer mappings are + explicit and verified. ## Examples @@ -53,6 +80,19 @@ classes: - has_agent ``` +### Also Correct in the Parsimonious Layer + +```yaml +classes: + CustodialEntity: + class_uri: schema:Organization + narrow_mappings: + - hc:Custodian +``` + +This is acceptable because `CustodialEntity` is intentionally broader than the +engineering `Custodian` class and serves as a semantic facade. + ## References 1. Liefke, K. (2024). *Natural Language Ontology and Semantic Theory*. @@ -62,4 +102,3 @@ classes: 2. Liefke, K. (2025). *Reduction and Unification in Natural Language Ontology*. Cambridge Elements in Semantics. DOI: `10.1017/9781009559683`. URL: https://www.cambridge.org/core/elements/abs/reduction-and-unification-in-natural-language-ontology/40F58ABA0D9C08958B5926F0CBDAD3CA - diff --git a/.opencode/rules/linkml/ontology-to-linkml-mapping-convention.md b/.opencode/rules/linkml/ontology-to-linkml-mapping-convention.md index ec73290252..c429bed193 100644 --- a/.opencode/rules/linkml/ontology-to-linkml-mapping-convention.md +++ b/.opencode/rules/linkml/ontology-to-linkml-mapping-convention.md @@ -271,6 +271,49 @@ Before committing ontology mappings: --- +## 6b. Parsimonious-to-Engineering Internal Mapping + +When working in `schemas/20251121/linkml/parsimony/`, you MUST distinguish two +different mapping tasks: + +1. **External ontology mapping** + - Use `class_uri`, `slot_uri`, and `*_mappings` against external ontologies. +2. **Internal cross-layer mapping** + - Document how the parsimonious hypernym is realized by engineering classes, + slots, and enums in `schemas/20251121/linkml/modules/`. + +### Rules for internal cross-layer mapping + +- The parsimonious class may be broader than multiple engineering classes. +- Do not pretend internal cross-layer mappings are exact if they are really + hypernym-to-hyponym relations. +- Use relative imports back to the engineering package so the bridge is visible + in LinkML source form. +- Treat the bridge as part of the ontology deliverable, not as separate prose. + +### Example + +```yaml +imports: + - ../classes/CustodialEntity + - ../../../modules/classes/Custodian + - ../../../modules/classes/CustodianObservation + +comments: + - >- + CustodialEntity is broader than the engineering Custodian class and must be + read together with narrower engineering reconstruction and observation classes. +``` + +### Internal mapping checklist + +- [ ] Did you state whether the parsimonious term is broader, narrower, close, or related to the engineering term? +- [ ] Did you avoid treating engineering-specific data objects as exact matches for broader conceptual nodes? +- [ ] Did you use relative imports from `schemas/20251121/linkml/parsimony/modules/` back to `schemas/20251121/linkml/modules/`? +- [ ] Did you explain how the parsimonious node becomes classes, enums, or slots in the engineering model? + +--- + ## 7. Common Ontology Prefixes for Mappings | Prefix | Namespace | Ontology | Use For | diff --git a/.opencode/rules/linkml/parsimony/class-naming-convention.md b/.opencode/rules/linkml/parsimony/class-naming-convention.md new file mode 100644 index 0000000000..415b41081e --- /dev/null +++ b/.opencode/rules/linkml/parsimony/class-naming-convention.md @@ -0,0 +1,67 @@ +# Rule: Parsimonious Class Naming Convention + +## Critical Convention + +Classes in `schemas/20251121/linkml/parsimony/` are conceptual by default. + +Do not append `Concept` to every class name unless the suffix expresses a real +semantic distinction that is necessary for understanding the model. + +## Rule + +1. Assume parsimonious classes are already hypernyms. + - Their conceptual status is given by the layer, not by the suffix. + +2. Prefer semantically informative names over meta-labels. + - Good: `Classification`, `Designation`, `PlaceContext`, `SourceResource` + - Weak: `TypeConcept`, `IdentifierConcept`, `PlaceConcept`, `SourceConcept` + +3. Avoid unnecessary collisions with engineering class names. + - If a broad parsimonious class would collide with an engineering class of a + narrower meaning, choose a distinct but still natural hypernym label. + - Example: prefer `CustodialEntity` over parsimonious `Custodian` when the + engineering ontology already uses `Custodian` for a narrower hub class. + +4. Keep names compact and readable in UML views. + - Parsimonious class names should help the dashboard communicate the semantic + backbone quickly. + +## Rationale + +- The parsimonious layer should look like a coherent conceptual ontology, not a + catalog of meta-marked placeholders. +- Removing repetitive `Concept` suffixes improves readability without losing + semantic clarity. +- Distinct natural labels reduce confusion when the parsimonious and engineering + layers are read side by side. + +## Examples + +### Better + +```yaml +classes: + Classification: + class_uri: skos:Concept + + Designation: + class_uri: crm:E41_Appellation +``` + +### Avoid + +```yaml +classes: + TypeConcept: + class_uri: skos:Concept + + IdentifierConcept: + class_uri: crm:E41_Appellation +``` + +## Checklist + +- [ ] Does the class name avoid redundant `Concept` suffixing? +- [ ] Is the class name semantically informative on its own? +- [ ] If the name differs from the engineering class, does it do so for a clear semantic reason? +- [ ] Will the name read well in UML and documentation? diff --git a/.opencode/rules/linkml/parsimony/semantic-entity-terminology.md b/.opencode/rules/linkml/parsimony/semantic-entity-terminology.md new file mode 100644 index 0000000000..b28528cebc --- /dev/null +++ b/.opencode/rules/linkml/parsimony/semantic-entity-terminology.md @@ -0,0 +1,36 @@ +# Rule: Semantic Entity Terminology + +## Critical Convention + +In `schemas/20251121/linkml/parsimony/`, the ontology is produced through a +parsimony methodology, but the modeled entities are not themselves to be called +"parsimonious entities". + +Use `semantic entity`, `semantic relation`, `semantic class`, or other +domain-appropriate wording when describing ontology elements. + +## Rule + +1. Reserve `parsimony` and `parsimonious` for the ontology layer, package, or + modeling methodology. + - Good: `parsimonious ontology`, `parsimony package`, `parsimony methodology` + +2. Do not describe modeled entities as `parsimonious entities`. + - Prefer `semantic entity`, `conceptual entity`, or a more specific term. + +3. In slot and class descriptions, prefer domain meaning over methodology labels. + - Good: `Connects a semantic entity to the source...` + - Bad: `Connects a parsimonious entity to the source...` + +## Rationale + +- Parsimony describes how the ontology is designed, not what kind of things its + entities are. +- The modeled nodes remain semantic/conceptual entities even when the ontology is + intentionally reduced. + +## Checklist + +- [ ] Is `parsimonious` used only for the layer, package, or method? +- [ ] Are modeled nodes described as semantic or conceptual entities instead? +- [ ] Do descriptions avoid conflating methodology with ontology semantics? diff --git a/.opencode/rules/linkml/parsimony/slot-hypernym-convention.md b/.opencode/rules/linkml/parsimony/slot-hypernym-convention.md new file mode 100644 index 0000000000..860873c8f8 --- /dev/null +++ b/.opencode/rules/linkml/parsimony/slot-hypernym-convention.md @@ -0,0 +1,84 @@ +# Rule: Parsimonious Slot Hypernym Convention + +## Critical Convention + +Slots in `schemas/20251121/linkml/parsimony/` MUST be modeled as conceptual +hypernyms over engineering predicates in `schemas/20251121/linkml/modules/`. + +Do not copy an engineering slot name into the parsimonious layer and merely add +an implementation suffix such as `_literal`, `_concept`, or `_value` when the +real intent is a broader semantic predicate. + +## Rule + +1. Start from the conceptual relation, not the engineering storage pattern. + - Ask which broader relation unifies the narrower engineering slots. + +2. Prefer parsimonious hypernyms over copied engineering names. + - Good: `accessed_under` + - Bad: `has_access_policy_literal` + +3. Use engineering slots as `narrow_mappings` when they are implementation-ready + refinements of the broader parsimonious predicate. + - Example: `accessed_under` -> `hc:has_access_policy` + +4. Avoid datatype-implementation suffixes in parsimonious slot names. + - Avoid `_literal`, `_string`, `_value`, `_concept` unless the distinction is + itself semantically necessary. + +5. Keep slot names in current verb-first style where possible. + - Examples: `designated_by`, `included_in`, `marked_as`, `situated_in_time` + +6. Avoid over-binding a slot name to one evidential source or implementation mechanism + when the parsimonious intent is broader. + - Prefer `grounded_in` over `derived_from_observation` + - Prefer `realized_through` over `generated_by_activity` + - Prefer `attested_in` over `documented_in` when the source relation is evidential + - Prefer `available_via` over `accessed_through` when the slot means channel of availability + +## Rationale + +- The parsimonious layer should expose semantic hubs, not mirror the engineering + schema file structure. +- Hypernym predicates make the bridge to multiple engineering hyponyms explicit. +- This keeps the parsimonious ontology stable even when engineering slots split, + merge, or change operational detail. + +## Examples + +### Wrong + +```yaml +slots: + has_access_policy_literal: + slot_uri: dcterms:accessRights + close_mappings: + - hc:has_access_policy +``` + +### Correct + +```yaml +slots: + accessed_under: + slot_uri: dcterms:accessRights + narrow_mappings: + - hc:has_access_policy +``` + +### Another Good Pattern + +```yaml +slots: + designated_by: + slot_uri: crm:P1_is_identified_by + narrow_mappings: + - hc:identified_by +``` + +## Checklist + +- [ ] Is the parsimonious slot broader than the engineering slot(s) it bridges? +- [ ] Does the name avoid implementation suffixes? +- [ ] Are engineering refinements expressed as `narrow_mappings` where appropriate? +- [ ] Does the slot name follow current verb-first naming style? diff --git a/.opencode/rules/linkml/slot-usage-minimization-rule.md b/.opencode/rules/linkml/slot-usage-minimization-rule.md index 09451484d7..b041b3dde9 100644 --- a/.opencode/rules/linkml/slot-usage-minimization-rule.md +++ b/.opencode/rules/linkml/slot-usage-minimization-rule.md @@ -89,6 +89,21 @@ A `slot_usage` entry MUST be kept if it provides ANY of the following: | **Inlined change** | `inlined: true` when generic is `false` | | **Identifier designation** | `identifier: true` for primary key | +### Parsimonious Layer Clarification + +In `schemas/20251121/linkml/parsimony/`, sparse `slot_usage` is allowed when it +documents a genuine conceptual narrowing from a generic parsimonious predicate to +one class-specific use. + +Examples of acceptable parsimonious `slot_usage`: + +- narrowing a generic `typed_as` predicate to a specific type concept +- making a generic identifier slot required for one conceptual hub +- clarifying that a broad conceptual slot is only used for evidential links in one class + +This does NOT relax the core rule: if the `slot_usage` simply repeats the generic +slot definition, it is still redundant and must be removed. + ## Decision Matrix | Scenario | Action | diff --git a/docs/plan/semantic_ontology/00-master-checklist.md b/docs/plan/semantic_ontology/00-master-checklist.md new file mode 100644 index 0000000000..8395992b81 --- /dev/null +++ b/docs/plan/semantic_ontology/00-master-checklist.md @@ -0,0 +1,60 @@ +# Semantic Parsimony Ontology - Master Checklist + +Status: planning + +## Phase 0 - Research and framing + +- [ ] Confirm the parsimonious ontology scope against PiCo, RiC-O, PROV-O, Schema.org, and selected ODP literature. +- [ ] Inventory the most important engineering modules, classes, and slots in `schemas/20251121/linkml/modules/`. +- [ ] Identify the 8-12 semantic hubs that cover most engineering concepts without collapsing important distinctions. +- [ ] Define inclusion criteria for parsimonious classes and slots. +- [ ] Define exclusion criteria for engineering-only details. + +## Phase 1 - Parsimonious conceptual design + +- [ ] Fix the class budget at roughly 10 classes. +- [ ] Fix the datatype slot budget at roughly 30 slots. +- [ ] Fix the object slot budget at roughly 50 slots. +- [ ] Decide which PiCo-style distinctions become explicit classes: observation, reconstruction, source, activity, agent, type, relation, identifier, name, place, time. +- [ ] Decide which distinctions remain engineering-only refinements. + +## Phase 2 - LinkML package structure + +- [x] Create `schemas/20251121/linkml/parsimony/` as a separate LinkML package. +- [x] Create `modules/classes/`, `modules/slots/`, `modules/enums/`, and `modules/mappings/` under the parsimony package. +- [x] Add a parsimonious root schema that imports the small module set. +- [x] Keep slots centralized; do not define inline slots in class files. +- [x] Keep imports relative to the engineering `modules/` directory where cross-package mappings are needed. + +## Phase 3 - Mapping to the engineering ontology + +- [x] Create dedicated mapping files under `schemas/20251121/linkml/parsimony/modules/mappings/`. +- [ ] For each parsimonious class, identify the engineering classes, enums, and slots it subsumes. +- [ ] For each mapping, document whether the engineering term is exact, broader, narrower, close, or related. +- [ ] Use verified ontology references from `data/ontology/` where external mappings are asserted. +- [ ] Document how hypernym concepts become database-like engineering structures. +- [x] Use relative imports from parsimonious modules to engineering modules via `../../../modules/...`. + +## Phase 4 - Rules and governance + +- [ ] Review `.opencode/rules/linkml/` for assumptions that are engineering-only. +- [ ] Propose amendments for parsimonious modeling where current rules are too narrow. +- [ ] Preserve core rules: verified mappings, class/property distinction, centralized slots, no inline slots, generic slots over bespoke predicates. +- [ ] Add or update rule text for cross-layer mapping between parsimonious hypernyms and engineering refinements. +- [ ] Add governance notes for when semantic simplicity is preferred over engineering completeness. + +## Phase 5 - Dashboard and UX + +- [x] Add `bronhouder.nl/parsimony` route. +- [x] Reuse the LinkML viewer page, layout, and UML viewer behavior. +- [x] Point the route at `/schemas/20251121/linkml/parsimony`. +- [x] Generate a separate manifest for the parsimonious schema package. +- [ ] Verify that the dashboard behaves correctly even while the package is still sparsely populated. + +## Phase 6 - Validation and delivery + +- [ ] Validate parsimonious YAML structure. +- [ ] Validate manifests and frontend loading. +- [ ] Validate mapping paths and import paths. +- [ ] Review the plan against the LinkML rules and document planned rule edits. +- [ ] Convert the plan into implementation tickets. diff --git a/docs/plan/semantic_ontology/01-reference-model-review.md b/docs/plan/semantic_ontology/01-reference-model-review.md new file mode 100644 index 0000000000..9e756c7ae3 --- /dev/null +++ b/docs/plan/semantic_ontology/01-reference-model-review.md @@ -0,0 +1,41 @@ +# Reference Model Review + +## What PiCo contributes + +PiCo is the most relevant reference because it stays small while still handling provenance, source anchoring, and interpretation. + +Useful PiCo lessons: + +- Reuse external ontologies aggressively instead of inventing bespoke top-level classes. +- Keep the conceptual centers explicit: `PersonObservation`, `PersonReconstruction`, and `Source`. +- Treat provenance as structural, not optional decoration. +- Allow the engineering/data layer to be richer than the conceptual layer. +- Use documentation, diagrams, and examples as part of the ontology product. + +## What to copy from PiCo + +- A small number of stable conceptual hubs. +- A strong observation/reconstruction pattern where evidence and interpretation are separated. +- Use of existing vocabularies such as Schema.org, PROV-O, and domain-specific vocabularies. +- Human-readable documentation that explains modeling intent rather than only listing terms. + +## What not to copy blindly + +- PiCo is person/history centered; the GLAM custodian domain is institution, holdings, access, provenance, and record-oriented. +- PiCo's class list should inspire modeling discipline, not determine class names. +- The parsimonious GLAM ontology must preserve room for archives, museums, libraries, and hybrid custodians. + +## Additional parsimonious ontology principles + +- Prefer semantic hubs over large taxonomies. +- Push local specialization into mappings and engineering refinements. +- Use object properties for real semantic relations; use datatype properties for compact descriptive facts. +- Prefer a few reusable generic predicates over many narrow bespoke predicates. + +## Consequence for this project + +The parsimonious ontology should function like a conceptual facade over the engineering ontology: + +- small enough for comprehension and UML browsing +- rich enough to express custodians, collections/record sets, provenance, access, identifiers, place, time, and classification +- explicit enough to explain how conceptual hypernyms are realized in the engineering model diff --git a/docs/plan/semantic_ontology/02-target-parsimonious-model.md b/docs/plan/semantic_ontology/02-target-parsimonious-model.md new file mode 100644 index 0000000000..7c46000784 --- /dev/null +++ b/docs/plan/semantic_ontology/02-target-parsimonious-model.md @@ -0,0 +1,81 @@ +# Target Parsimonious Model + +## Modeling target + +Target size: + +- about 10 classes +- about 30 datatype slots +- about 50 object slots + +This is a budget, not a hard law, but the plan should resist drift beyond it. + +## Candidate class set + +Proposed conceptual hubs: + +1. `CustodialEntity` +2. `Holding` +3. `SourceResource` +4. `Observation` +5. `Reconstruction` +6. `Agent` +7. `Activity` +8. `PlaceContext` +9. `Designation` +10. `Classification` + +Possible merges to keep the budget tight: + +- merge `Holding` with `RecordSetOrCollection` if holdings can be modeled relationally +- merge `Name` and `Identifier` under one contextual class when needed +- keep time as datatypes/structured slots instead of a standalone class unless evidence shows otherwise + +Naming convention: + +- avoid the suffix `Concept` unless needed to disambiguate a real modeling distinction +- assume parsimonious classes are conceptual/hypernymic by default +- prefer semantically informative names such as `Classification` or `Designation` over meta-labels such as `TypeConcept` + +## Candidate datatype slot groups + +- labels and literals +- identifiers and codes +- dates and temporal literals +- URLs and references +- free-text notes and scope notes +- counts and scalar values +- language/status/access literals + +## Candidate object slot groups + +- type/classification +- part-whole +- custody/holding +- provenance and derivation +- source/evidence links +- access/publication links +- location links +- organizational relations +- mapping to engineering classes and slots + +Current scaffold now covers early examples of: + +- part-whole +- custody/holding +- provenance and derivation +- source/evidence links +- access/publication links +- location links +- organizational relations + +## Design rule for admission + +A parsimonious class or slot should exist only if at least one of these is true: + +- it is a recurring semantic hub across many engineering modules +- it is required to explain provenance/evidence correctly +- it substantially improves UML readability and conceptual documentation +- it is needed as the source node for many engineering mappings + +Otherwise, the concept remains engineering-only. diff --git a/docs/plan/semantic_ontology/03-linkml-module-layout.md b/docs/plan/semantic_ontology/03-linkml-module-layout.md new file mode 100644 index 0000000000..b6dfc21076 --- /dev/null +++ b/docs/plan/semantic_ontology/03-linkml-module-layout.md @@ -0,0 +1,45 @@ +# LinkML Module Layout + +## Package structure + +Planned package: + +```text +schemas/20251121/linkml/parsimony/ + metadata.yaml + modules/ + classes/ + slots/ + enums/ + mappings/ +``` + +## Layout principles + +- Keep the parsimonious package separate from the engineering package. +- Reuse the same LinkML authoring conventions as the engineering ontology. +- Keep slot definitions centralized under `modules/slots/`. +- Keep class files small and import the slots they use. +- Use a minimal number of files; avoid unnecessary fragmentation. + +## Cross-package references + +When the parsimonious package references engineering files, the relative path should be computed from the parsimonious module location back to `schemas/20251121/linkml/modules/`. + +Examples from `schemas/20251121/linkml/parsimony/modules/classes/`: + +- engineering class import: `../../../modules/classes/Archive.yaml` +- engineering slot import: `../../../modules/slots/hold.yaml` +- engineering mapping support file: `../../../modules/mappings/...` + +Examples from `schemas/20251121/linkml/parsimony/modules/mappings/`: + +- engineering class import: `../../../modules/classes/...` +- engineering slot import: `../../../modules/slots/...` + +## File design guidance + +- Use a root `metadata.yaml` for prefixes and package-level metadata. +- Keep a small root schema once implementation starts. +- Reserve `modules/mappings/` for explicit parsimonious-to-engineering alignment artifacts. +- Treat mapping files as part of the ontology, not auxiliary notes. diff --git a/docs/plan/semantic_ontology/04-engineering-mapping-strategy.md b/docs/plan/semantic_ontology/04-engineering-mapping-strategy.md new file mode 100644 index 0000000000..b77ae34116 --- /dev/null +++ b/docs/plan/semantic_ontology/04-engineering-mapping-strategy.md @@ -0,0 +1,68 @@ +# Engineering Mapping Strategy + +## Core requirement + +The mapping between the parsimonious ontology and the engineering ontology is a core deliverable because it explains how broad semantic concepts become concrete operational data structures. + +## Mapping pattern + +For every parsimonious concept, document: + +- the semantic intent of the parsimonious class/slot +- the engineering classes it covers +- the engineering slots it covers +- the engineering enums or type classes it depends on +- whether each relation is exact, broad, narrow, close, or related + +## Expected asymmetry + +The mapping is intentionally asymmetric: + +- parsimonious classes are often hypernyms +- engineering classes are often narrower data-ready realizations +- many engineering structures may map upward into one parsimonious node + +Example pattern: + +```text +Parsimonious class: Custodian + -> broad semantic parent of AcademicArchive, Museum, Library, PlatformCustodian, ParishArchive, etc. + +Parsimonious slot: holds + -> realized by engineering slots such as hold, hold_record_set, has_custodian, has_member, is_or_was_holder_of, depending on context +``` + +## Mapping rules that must remain active + +- exact vs broad vs narrow mappings must be explicit +- class-to-class and slot-to-property distinctions must be preserved +- external ontology mappings must be verified against `data/ontology/` +- generic predicate discipline must be preserved even in the parsimonious layer + +## New mapping deliverables + +Planned outputs under `schemas/20251121/linkml/parsimony/modules/mappings/`: + +- class alignment matrix +- slot alignment matrix +- type-system bridge across classes, enums, and typing predicates +- hypernym-to-engineering realization notes +- UML-friendly conceptual-to-engineering bridge views + +Verified external ontology anchors should be added directly to parsimonious +classes and slots using LinkML mapping fields such as `broad_mappings`, +`narrow_mappings`, `close_mappings`, and `related_mappings`. + +Current anchor examples include: + +- `schema:Organization`, `schema:CreativeWork`, `schema:Place`, `schema:url`, `schema:startDate` +- `dcterms:source`, `dcterms:accessRights` +- `prov:Entity`, `prov:Activity`, `prov:Agent`, `prov:wasDerivedFrom`, `prov:wasGeneratedBy`, `prov:generated`, `prov:used` +- `crm:E39_Actor`, `crm:E41_Appellation`, `crm:E53_Place`, `crm:E55_Type`, `crm:E78_Curated_Holding`, `crm:P1_is_identified_by`, `crm:P4_has_time-span` +- `rico:Agent`, `rico:RecordSet`, `rico:Identifier`, `rico:isOrWasHolderOf`, `rico:hasOrHadIdentifier` +- `skos:Concept`, `skos:prefLabel`, `skos:note` +- `pico:PersonObservation`, `pico:PersonReconstruction` + +## Why this matters + +Without this bridge, the parsimonious layer risks becoming only a simplified diagram. With the bridge, it becomes an explanatory semantic interface for databases, extraction pipelines, and engineering-level knowledge graph modeling. diff --git a/docs/plan/semantic_ontology/05-rule-updates.md b/docs/plan/semantic_ontology/05-rule-updates.md new file mode 100644 index 0000000000..c749fcf56c --- /dev/null +++ b/docs/plan/semantic_ontology/05-rule-updates.md @@ -0,0 +1,65 @@ +# Rule Updates for Parsimony + +## Why rule work is required + +The current `.opencode/rules/linkml/` set is optimized for the engineering ontology. Much of it remains correct for the parsimonious package, but several rules need extension so the parsimonious layer is not forced into engineering-scale detail. + +## Rules to keep as-is + +- verified ontology mappings +- ontology detection from actual ontology files +- mapping specificity: exact vs broad vs narrow +- centralized slots +- no inline class-file slots +- generic slots over bespoke predicates +- LinkML YAML hygiene and import discipline + +## Rules that need extension or clarification + +### 1. Engineering parsimony vs semantic parsimony + +Current rule: `engineering-parsimony-and-domain-modeling-rule.md` + +Needed extension: + +- distinguish the engineering ontology from a semantic facade ontology +- allow a parsimonious package to intentionally collapse multiple engineering classes into one conceptual hypernym +- clarify that this is not a violation of semantic consistency when the downward mapping is explicit + +### 2. Semantic consistency over simplicity + +Current rule emphasis is strongly pro-structure for engineering migrations. + +Needed extension: + +- clarify that semantic consistency across layers can sometimes justify fewer classes in the parsimonious package +- state that engineering richness is preserved in mappings rather than duplicated in the parsimonious layer + +### 3. Slot usage minimization + +Needed extension: + +- permit sparse, meaningful `slot_usage` in the parsimonious layer when it serves conceptual narrowing or bridge documentation +- keep redundant overrides prohibited + +### 4. Ontology-to-LinkML mapping convention + +Needed extension: + +- add a dedicated section for parsimonious-to-engineering internal mappings +- distinguish external ontology alignment from internal cross-layer alignment + +## Proposed new rule themes + +- parsimonious layer as hypernym layer +- mandatory concept-to-engineering realization mapping +- no silent semantic collapse: every collapsed concept must list covered engineering refinements +- dashboard-first documentation for parsimonious schemas +- parsimonious slots must prefer hypernym predicates over copied engineering slot names with implementation suffixes +- parsimonious classes should avoid redundant `Concept` suffixes and use semantically informative names +- parsimonious slot names should avoid over-binding to one source type or one implementation mechanism when a broader evidential or process relation is intended +- every external class/property mapping in the parsimonious package must be verifiable in `data/ontology/` with zero tolerance for unverified references + +## Delivery implication + +Rule editing should be treated as part of ontology implementation, not post hoc cleanup. diff --git a/docs/plan/semantic_ontology/06-dashboard-and-uml-viewer.md b/docs/plan/semantic_ontology/06-dashboard-and-uml-viewer.md new file mode 100644 index 0000000000..e170a3b5a5 --- /dev/null +++ b/docs/plan/semantic_ontology/06-dashboard-and-uml-viewer.md @@ -0,0 +1,33 @@ +# Dashboard and UML Viewer + +## Goal + +Expose the parsimonious ontology at `bronhouder.nl/parsimony` using the same LinkML viewer page, layout, and UML interaction pattern as `bronhouder.nl/linkml`. + +## UI approach + +- reuse the existing `LinkMLViewerPage` +- switch only the schema root and page labels +- load schemas from `/schemas/20251121/linkml/parsimony` +- generate a separate manifest for that schema root + +## Requirements + +- no new viewer implementation +- same sidebar, schema detail rendering, mapping badges, and UML widgets +- same public route behavior +- graceful empty-state handling while the parsimonious package is still under construction + +## Technical plan + +- parameterize the viewer by schema base path +- add `/parsimony` as a public route +- add a navigation item under the ontology menu +- generate `frontend/public/schemas/20251121/linkml/parsimony/manifest.json` + +## Validation + +- route opens without authentication issues +- manifest loads from the parsimonious schema root +- selected schema loads correctly from the parsimonious package +- switching between `/linkml` and `/parsimony` does not leak cached schemas across roots diff --git a/docs/plan/semantic_ontology/07-implementation-phases.md b/docs/plan/semantic_ontology/07-implementation-phases.md new file mode 100644 index 0000000000..2558947b0c --- /dev/null +++ b/docs/plan/semantic_ontology/07-implementation-phases.md @@ -0,0 +1,37 @@ +# Implementation Phases + +## Phase 1 - Research and reduction + +- study PiCo documentation and article material +- identify the smallest reusable semantic hubs for GLAM custodians +- decide what stays conceptual and what remains engineering-only + +## Phase 2 - Parsimonious LinkML scaffolding + +- create the package structure +- create package metadata and root schema +- define the first small set of classes and slots + +## Phase 3 - Bridge to engineering ontology + +- create explicit mapping modules +- document downward realization from hypernyms to engineering classes/slots/enums +- verify external ontology mappings against `data/ontology/` + +## Phase 4 - Rule revisions + +- edit or extend the relevant LinkML rules +- document which rules are shared across both ontology layers +- document which rules are engineering-only and which become dual-layer + +## Phase 5 - Dashboard rollout + +- enable `/parsimony` +- verify manifests, routing, and UML rendering +- surface the package even before full ontology completion + +## Phase 6 - Iterative population + +- add the final limited class set +- add the slot budget in a controlled way +- resist ontology growth unless justified in the mapping docs diff --git a/docs/plan/semantic_ontology/README.md b/docs/plan/semantic_ontology/README.md new file mode 100644 index 0000000000..9b6be41a9d --- /dev/null +++ b/docs/plan/semantic_ontology/README.md @@ -0,0 +1,28 @@ +# Semantic Parsimony Ontology Plan + +This plan defines how to derive a parsimonious LinkML ontology from the engineering ontology in `schemas/20251121/linkml/modules/` while keeping the engineering model as the authoritative implementation layer. + +Goals: + +- Keep the parsimonious ontology deliberately small: about 10 classes, 30 datatype properties, and 50 object properties. +- Reuse the PiCo pattern: small conceptual hub classes, explicit evidence/provenance, and strong reuse of external vocabularies. +- Make the parsimonious-to-engineering mapping a first-class deliverable, not an afterthought. +- Expose the parsimonious LinkML schema in the same dashboard/viewer pattern used for `bronhouder.nl/linkml`. +- Document which existing LinkML rules stay valid, which need clarification, and which need extension for the parsimonious layer. + +Document index: + +- `00-master-checklist.md` - implementation tracker +- `01-reference-model-review.md` - PiCo and related parsimonious ontology lessons +- `02-target-parsimonious-model.md` - target class/property budget and conceptual shape +- `03-linkml-module-layout.md` - file layout and schema packaging plan +- `04-engineering-mapping-strategy.md` - core mapping strategy to the engineering ontology +- `05-rule-updates.md` - required updates/extensions to `.opencode/rules/linkml/` +- `06-dashboard-and-uml-viewer.md` - `bronhouder.nl/parsimony` rollout plan +- `07-implementation-phases.md` - phased execution plan + +Core stance: + +- The parsimonious ontology is the semantic/conceptual layer. +- The engineering ontology remains the data-rich operational layer. +- Hypernym-style parsimonious concepts must map downward into concrete engineering classes, enums, and slots with verified LinkML mappings and explicit rationale. diff --git a/frontend/public/data/heritage_custodian_ontology.mmd b/frontend/public/data/heritage_custodian_ontology.mmd index 12744947a7..1d242d7860 100644 --- a/frontend/public/data/heritage_custodian_ontology.mmd +++ b/frontend/public/data/heritage_custodian_ontology.mmd @@ -1,7 +1,7 @@ ```mermaid classDiagram %% Generated from LinkML manifest: /schemas/20251121/linkml/manifest.json -%% Manifest generated: 2026-02-20T12:44:35.583Z +%% Manifest generated: 2026-03-13T15:26:06.249Z direction LR class AbbreviatedTitle class AbbreviationVariant diff --git a/frontend/public/schemas/20251121/linkml/manifest.json b/frontend/public/schemas/20251121/linkml/manifest.json index 414c987f7e..3db415ef42 100644 --- a/frontend/public/schemas/20251121/linkml/manifest.json +++ b/frontend/public/schemas/20251121/linkml/manifest.json @@ -1,5 +1,5 @@ { - "generated": "2026-02-20T12:32:55.895Z", + "generated": "2026-03-13T15:26:06.249Z", "schemaRoot": "/schemas/20251121/linkml", "totalFiles": 2187, "categoryCounts": { diff --git a/frontend/public/schemas/20251121/linkml/modules/schemata_bronhouder.zip b/frontend/public/schemas/20251121/linkml/modules/schemata_bronhouder.zip new file mode 100644 index 0000000000..1487e90cb4 Binary files /dev/null and b/frontend/public/schemas/20251121/linkml/modules/schemata_bronhouder.zip differ diff --git a/frontend/public/schemas/20251121/linkml/parsimony/manifest.json b/frontend/public/schemas/20251121/linkml/parsimony/manifest.json new file mode 100644 index 0000000000..dda1e1e4ca --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/manifest.json @@ -0,0 +1,222 @@ +{ + "generated": "2026-03-13T15:26:06.258Z", + "schemaRoot": "/schemas/20251121/linkml/parsimony", + "totalFiles": 37, + "categoryCounts": { + "main": 2, + "class": 10, + "slot": 21, + "module": 4 + }, + "categories": [ + { + "name": "main", + "displayName": "Main Schemas", + "files": [ + { + "name": "metadata", + "path": "metadata.yaml", + "category": "main" + }, + { + "name": "parsimony_core", + "path": "parsimony_core.yaml", + "category": "main" + } + ] + }, + { + "name": "class", + "displayName": "Classes", + "files": [ + { + "name": "Activity", + "path": "modules/classes/Activity.yaml", + "category": "class" + }, + { + "name": "Agent", + "path": "modules/classes/Agent.yaml", + "category": "class" + }, + { + "name": "Classification", + "path": "modules/classes/Classification.yaml", + "category": "class" + }, + { + "name": "CustodialEntity", + "path": "modules/classes/CustodialEntity.yaml", + "category": "class" + }, + { + "name": "Designation", + "path": "modules/classes/Designation.yaml", + "category": "class" + }, + { + "name": "Holding", + "path": "modules/classes/Holding.yaml", + "category": "class" + }, + { + "name": "Observation", + "path": "modules/classes/Observation.yaml", + "category": "class" + }, + { + "name": "PlaceContext", + "path": "modules/classes/PlaceContext.yaml", + "category": "class" + }, + { + "name": "Reconstruction", + "path": "modules/classes/Reconstruction.yaml", + "category": "class" + }, + { + "name": "SourceResource", + "path": "modules/classes/SourceResource.yaml", + "category": "class" + } + ] + }, + { + "name": "slot", + "displayName": "Slots", + "files": [ + { + "name": "accessed_under", + "path": "modules/slots/accessed_under.yaml", + "category": "slot" + }, + { + "name": "attested_in", + "path": "modules/slots/attested_in.yaml", + "category": "slot" + }, + { + "name": "available_via", + "path": "modules/slots/available_via.yaml", + "category": "slot" + }, + { + "name": "carried_out_by", + "path": "modules/slots/carried_out_by.yaml", + "category": "slot" + }, + { + "name": "derived_from_source", + "path": "modules/slots/derived_from_source.yaml", + "category": "slot" + }, + { + "name": "designated_by", + "path": "modules/slots/designated_by.yaml", + "category": "slot" + }, + { + "name": "grounded_in", + "path": "modules/slots/grounded_in.yaml", + "category": "slot" + }, + { + "name": "has_label_literal", + "path": "modules/slots/has_label_literal.yaml", + "category": "slot" + }, + { + "name": "has_note_literal", + "path": "modules/slots/has_note_literal.yaml", + "category": "slot" + }, + { + "name": "has_provenance_note", + "path": "modules/slots/has_provenance_note.yaml", + "category": "slot" + }, + { + "name": "has_uri_literal", + "path": "modules/slots/has_uri_literal.yaml", + "category": "slot" + }, + { + "name": "holds", + "path": "modules/slots/holds.yaml", + "category": "slot" + }, + { + "name": "included_in", + "path": "modules/slots/included_in.yaml", + "category": "slot" + }, + { + "name": "located_in", + "path": "modules/slots/located_in.yaml", + "category": "slot" + }, + { + "name": "marked_as", + "path": "modules/slots/marked_as.yaml", + "category": "slot" + }, + { + "name": "occurred_on", + "path": "modules/slots/occurred_on.yaml", + "category": "slot" + }, + { + "name": "organized_within", + "path": "modules/slots/organized_within.yaml", + "category": "slot" + }, + { + "name": "realized_through", + "path": "modules/slots/realized_through.yaml", + "category": "slot" + }, + { + "name": "reconstructs", + "path": "modules/slots/reconstructs.yaml", + "category": "slot" + }, + { + "name": "situated_in_time", + "path": "modules/slots/situated_in_time.yaml", + "category": "slot" + }, + { + "name": "typed_as", + "path": "modules/slots/typed_as.yaml", + "category": "slot" + } + ] + }, + { + "name": "module", + "displayName": "Modules", + "files": [ + { + "name": "parsimony_engineering_bridge", + "path": "modules/mappings/parsimony_engineering_bridge.yaml", + "category": "module" + }, + { + "name": "parsimony_engineering_class_alignments", + "path": "modules/mappings/parsimony_engineering_class_alignments.yaml", + "category": "module" + }, + { + "name": "parsimony_engineering_slot_alignments", + "path": "modules/mappings/parsimony_engineering_slot_alignments.yaml", + "category": "module" + }, + { + "name": "parsimony_engineering_type_bridge", + "path": "modules/mappings/parsimony_engineering_type_bridge.yaml", + "category": "module" + } + ] + } + ] +} \ No newline at end of file diff --git a/frontend/public/schemas/20251121/linkml/parsimony/metadata.yaml b/frontend/public/schemas/20251121/linkml/parsimony/metadata.yaml new file mode 100644 index 0000000000..22852703f9 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/metadata.yaml @@ -0,0 +1,29 @@ +id: https://nde.nl/ontology/hc/parsimony/metadata +name: heritage_custodian_parsimony_metadata +title: Heritage Custodian Parsimony Ontology - Metadata +description: >- + Metadata root for the parsimonious LinkML package that will provide a + conceptual facade over the engineering ontology in ../modules/. +version: 0.1.0 +license: https://creativecommons.org/licenses/by-sa/4.0/ +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# + prov: http://www.w3.org/ns/prov# + pico: https://personsincontext.org/model# + schema: http://schema.org/ + rico: https://www.ica.org/standards/RiC/ontology# + dcterms: http://purl.org/dc/terms/ + rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# + rdfs: http://www.w3.org/2000/01/rdf-schema# + owl: http://www.w3.org/2002/07/owl# +default_prefix: hc +imports: + - linkml:types +slots: + ontology_layer: + description: >- + Annotation indicating whether a schema element belongs to the parsimonious + conceptual layer or to a mapped engineering realization. + range: string diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Activity.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Activity.yaml new file mode 100644 index 0000000000..f7caa80239 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Activity.yaml @@ -0,0 +1,33 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Activity +name: Activity +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/carried_out_by + - ../slots/attested_in + - ../slots/located_in + - ../slots/occurred_on + - ../slots/reconstructs + - ../slots/situated_in_time + - ../slots/marked_as +classes: + Activity: + class_uri: prov:Activity + description: Broad class for provenance-bearing actions, including retrieval, curation, and reconstruction. + close_mappings: + - crm:E7_Activity + slots: + - has_label_literal + - carried_out_by + - attested_in + - located_in + - occurred_on + - reconstructs + - situated_in_time + - marked_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Agent.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Agent.yaml new file mode 100644 index 0000000000..84ca55c137 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Agent.yaml @@ -0,0 +1,28 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Agent +name: Agent +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + schema: http://schema.org/ + rico: https://www.ica.org/standards/RiC/ontology# +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/designated_by + - ../slots/typed_as +classes: + Agent: + class_uri: prov:Agent + description: Broad agent class used for people, organizations, or software agents active in provenance chains. + close_mappings: + - rico:Agent + - schema:Person + - schema:Organization + narrow_mappings: + - hc:Custodian + slots: + - has_label_literal + - designated_by + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Classification.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Classification.yaml new file mode 100644 index 0000000000..b7dc36e280 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Classification.yaml @@ -0,0 +1,21 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Classification +name: Classification +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_note_literal +classes: + Classification: + class_uri: skos:Concept + description: Broad conceptual type node used for classification, typology, and semantic narrowing. + broad_mappings: + - crm:E55_Type + slots: + - has_label_literal + - has_note_literal diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/CustodialEntity.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/CustodialEntity.yaml new file mode 100644 index 0000000000..c1b3bdbd06 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/CustodialEntity.yaml @@ -0,0 +1,45 @@ +id: https://nde.nl/ontology/hc/parsimony/class/CustodialEntity +name: CustodialEntity +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + rico: https://www.ica.org/standards/RiC/ontology# + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_note_literal + - ../slots/has_uri_literal + - ../slots/available_via + - ../slots/accessed_under + - ../slots/holds + - ../slots/designated_by + - ../slots/located_in + - ../slots/organized_within + - ../slots/has_provenance_note + - ../slots/marked_as + - ../slots/typed_as +classes: + CustodialEntity: + class_uri: schema:Organization + description: Broad conceptual class for a heritage custodian or custodial body. + broad_mappings: + - crm:E39_Actor + - rico:Agent + narrow_mappings: + - hc:Custodian + slots: + - has_label_literal + - has_note_literal + - has_uri_literal + - available_via + - accessed_under + - holds + - designated_by + - located_in + - organized_within + - has_provenance_note + - marked_as + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Designation.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Designation.yaml new file mode 100644 index 0000000000..fab995bfea --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Designation.yaml @@ -0,0 +1,23 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Designation +name: Designation +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + rico: https://www.ica.org/standards/RiC/ontology# +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_uri_literal + - ../slots/typed_as +classes: + Designation: + class_uri: crm:E41_Appellation + description: Broad concept for identifiers, names, codes, and appellations used to identify entities. + narrow_mappings: + - rico:Identifier + slots: + - has_label_literal + - has_uri_literal + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Holding.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Holding.yaml new file mode 100644 index 0000000000..54dacb796b --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Holding.yaml @@ -0,0 +1,37 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Holding +name: Holding +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + rico: https://www.ica.org/standards/RiC/ontology# + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_note_literal + - ../slots/available_via + - ../slots/attested_in + - ../slots/accessed_under + - ../slots/included_in + - ../slots/situated_in_time + - ../slots/marked_as + - ../slots/typed_as +classes: + Holding: + class_uri: rico:RecordSet + description: Broad conceptual class for a holding, record set, collection, or curated body of material. + broad_mappings: + - crm:E78_Curated_Holding + narrow_mappings: + - hc:CustodianCollection + slots: + - has_label_literal + - has_note_literal + - available_via + - attested_in + - accessed_under + - included_in + - situated_in_time + - marked_as + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Observation.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Observation.yaml new file mode 100644 index 0000000000..97e40d5dff --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Observation.yaml @@ -0,0 +1,31 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Observation +name: Observation +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + crm: http://www.cidoc-crm.org/cidoc-crm/ + pico: https://personsincontext.org/model# +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_note_literal + - ../slots/attested_in + - ../slots/occurred_on + - ../slots/has_provenance_note +classes: + Observation: + class_uri: prov:Entity + description: Evidence-bearing observation anchored in a source and usable for later reconstruction. + narrow_mappings: + - pico:PersonObservation + - hc:CustodianObservation + close_mappings: + - crm:E73_Information_Object + slots: + - has_label_literal + - has_note_literal + - attested_in + - has_provenance_note + - occurred_on diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/PlaceContext.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/PlaceContext.yaml new file mode 100644 index 0000000000..30e375cf9f --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/PlaceContext.yaml @@ -0,0 +1,25 @@ +id: https://nde.nl/ontology/hc/parsimony/class/PlaceContext +name: PlaceContext +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_uri_literal + - ../slots/typed_as +classes: + PlaceContext: + class_uri: schema:Place + description: Broad place class for named locations used in custodial description and provenance. + broad_mappings: + - crm:E53_Place + narrow_mappings: + - hc:CustodianPlace + slots: + - has_label_literal + - has_uri_literal + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/README.md b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/README.md new file mode 100644 index 0000000000..0e0cec6040 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/README.md @@ -0,0 +1,5 @@ +# Parsimonious class modules + +This directory will hold the small conceptual class set for the parsimonious ontology. + +Planned scale: about 10 classes. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Reconstruction.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Reconstruction.yaml new file mode 100644 index 0000000000..347ccd696f --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/Reconstruction.yaml @@ -0,0 +1,33 @@ +id: https://nde.nl/ontology/hc/parsimony/class/Reconstruction +name: Reconstruction +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + pico: https://personsincontext.org/model# +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/grounded_in + - ../slots/derived_from_source + - ../slots/realized_through + - ../slots/situated_in_time + - ../slots/typed_as +classes: + Reconstruction: + class_uri: prov:Entity + description: Conceptual entity reconstructed from one or more observations. + narrow_mappings: + - pico:PersonReconstruction + related_mappings: + - hc:CustodianNameConsensus + - hc:CustodianLegalStatus + - hc:CustodianPlace + slots: + - has_label_literal + - grounded_in + - derived_from_source + - realized_through + - situated_in_time + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/SourceResource.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/SourceResource.yaml new file mode 100644 index 0000000000..eb485668f3 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/classes/SourceResource.yaml @@ -0,0 +1,30 @@ +id: https://nde.nl/ontology/hc/parsimony/class/SourceResource +name: SourceResource +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + dcterms: http://purl.org/dc/terms/ +default_prefix: hc +imports: + - linkml:types + - ../slots/has_label_literal + - ../slots/has_uri_literal + - ../slots/available_via + - ../slots/typed_as +classes: + SourceResource: + class_uri: schema:CreativeWork + description: Broad conceptual class for a source, source file, archival object, or documentary carrier. + broad_mappings: + - crm:E73_Information_Object + close_mappings: + - dcterms:BibliographicResource + narrow_mappings: + - hc:CustodianSourceFile + slots: + - has_label_literal + - has_uri_literal + - available_via + - typed_as diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/enums/README.md b/frontend/public/schemas/20251121/linkml/parsimony/modules/enums/README.md new file mode 100644 index 0000000000..70bac77da1 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/enums/README.md @@ -0,0 +1,3 @@ +# Parsimonious enum modules + +This directory will hold only the enum files that remain necessary after semantic reduction. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/README.md b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/README.md new file mode 100644 index 0000000000..3670c16809 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/README.md @@ -0,0 +1,5 @@ +# Parsimonious-engineering mapping modules + +This directory will contain the explicit bridge between the parsimonious ontology and the engineering ontology in `../../../modules/`. + +Use relative references from parsimonious modules back to the engineering package so the mapping remains self-documenting inside LinkML. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_bridge.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_bridge.yaml new file mode 100644 index 0000000000..aa03737167 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_bridge.yaml @@ -0,0 +1,45 @@ +id: https://nde.nl/ontology/hc/parsimony/mappings/parsimony-engineering-bridge +name: parsimony_engineering_bridge +title: Parsimony to Engineering Bridge +description: >- + Mapping scaffold linking the parsimonious conceptual layer to the engineering + ontology in ../../../modules/. +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types + - ../classes/CustodialEntity + - ../classes/Holding + - ../classes/Observation + - ../classes/Reconstruction + - ../classes/PlaceContext + - ../classes/SourceResource + - ../classes/Designation + - ../classes/Classification + - ../../../modules/classes/Custodian + - ../../../modules/classes/CustodianCollection + - ../../../modules/classes/CustodianObservation + - ../../../modules/classes/CustodianPlace + - ../../../modules/slots/hold + - ../../../modules/slots/identified_by +comments: + - >- + CustodialEntity is a hypernym over engineering classes such as Custodian, + CustodianArchive, MuseumArchive, MunicipalArchive, and related institutional + specializations. + - >- + Holding is a hypernym over engineering classes such as + CustodianCollection and multiple RecordSetType or archive holding classes. + - >- + Observation is a hypernym over engineering evidence classes such as + CustodianObservation and similar source-attributed statements. + - >- + Reconstruction is a bridge concept for engineering reconstructed entities + such as CustodianNameConsensus, CustodianLegalStatus, and CustodianPlace. + - >- + Parsimonious slots must be read together with engineering slots such as + identified_by and hold, using broadMatch and narrowMatch semantics rather + than assuming one-to-one equivalence. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_class_alignments.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_class_alignments.yaml new file mode 100644 index 0000000000..c869e6e353 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_class_alignments.yaml @@ -0,0 +1,59 @@ +id: https://nde.nl/ontology/hc/parsimony/mappings/parsimony-engineering-class-alignments +name: parsimony_engineering_class_alignments +title: Parsimonious to Engineering Class Alignments +description: >- + Detailed class-level bridge between parsimonious hypernyms and engineering + realizations. +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types + - ../classes/CustodialEntity + - ../classes/Holding + - ../classes/Observation + - ../classes/Reconstruction + - ../classes/SourceResource + - ../classes/PlaceContext + - ../classes/Designation + - ../classes/Classification + - ../../../modules/classes/Custodian + - ../../../modules/classes/CustodianCollection + - ../../../modules/classes/CustodianObservation + - ../../../modules/classes/CustodianPlace + - ../../../modules/classes/CustodianLegalStatus + - ../../../modules/classes/CustodianNameConsensus + - ../../../modules/classes/CustodianSourceFile +comments: + - >- + CLASS ALIGNMENT: CustodialEntity -> Custodian is a narrow mapping. The + parsimonious node stands above the engineering hub plus narrower institutional + archive and custodian subtypes. + - >- + CLASS ALIGNMENT: Holding -> CustodianCollection is a narrow mapping. + The parsimonious node should also absorb multiple archive-specific RecordSetType + engineering classes as narrower realizations of one conceptual holding family. + - >- + CLASS ALIGNMENT: Observation -> CustodianObservation is a narrow mapping. + Observation remains the evidence-level hypernym for source-attributed records. + - >- + CLASS ALIGNMENT: Reconstruction -> CustodianLegalStatus, CustodianNameConsensus, + and CustodianPlace are narrow mappings. The parsimonious reconstruction node + intentionally collapses multiple engineering reconstruction products. + - >- + CLASS ALIGNMENT: SourceResource -> CustodianSourceFile is a narrow mapping. + The engineering class acts as a root source bundle, while the parsimonious class + remains a broader documentary carrier concept. + - >- + CLASS ALIGNMENT: PlaceContext -> CustodianPlace is a narrow mapping. The + engineering model adds reconstruction provenance and locality detail absent from + the parsimonious layer. + - >- + CLASS ALIGNMENT: Designation bridges to engineering identifier-bearing + structures through slots such as identified_by and has_name rather than a single + exact engineering class. + - >- + CLASS ALIGNMENT: Classification bridges to engineering type classes and enums, + including CustodianType and many domain-specific type collections. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_slot_alignments.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_slot_alignments.yaml new file mode 100644 index 0000000000..4433b7d8c9 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_slot_alignments.yaml @@ -0,0 +1,99 @@ +id: https://nde.nl/ontology/hc/parsimony/mappings/parsimony-engineering-slot-alignments +name: parsimony_engineering_slot_alignments +title: Parsimonious to Engineering Slot Alignments +description: >- + Detailed slot-level bridge showing how parsimonious predicates map to richer + engineering slots. +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types + - ../slots/available_via + - ../slots/accessed_under + - ../slots/designated_by + - ../slots/holds + - ../slots/attested_in + - ../slots/grounded_in + - ../slots/derived_from_source + - ../slots/realized_through + - ../slots/included_in + - ../slots/located_in + - ../slots/marked_as + - ../slots/organized_within + - ../slots/reconstructs + - ../slots/situated_in_time + - ../slots/typed_as + - ../slots/carried_out_by + - ../../../modules/slots/derive_from + - ../../../modules/slots/encompassed_by + - ../../../modules/slots/generated_by + - ../../../modules/slots/has_access_policy + - ../../../modules/slots/has_status + - ../../../modules/slots/hold + - ../../../modules/slots/identified_by + - ../../../modules/slots/has_source + - ../../../modules/slots/observe + - ../../../modules/slots/part_of + - ../../../modules/slots/refer_to + - ../../../modules/slots/temporal_extent +comments: + - >- + SLOT ALIGNMENT: available_via is a broader parsimonious availability + predicate + that bridges to engineering URL, portal, and access-point slots without + reproducing all delivery mechanics. + - >- + SLOT ALIGNMENT: holds is broader than engineering hold. The parsimonious slot + should cover custody, stewardship, and holding relations that are split across + multiple engineering slots and class contexts. + - >- + SLOT ALIGNMENT: designated_by is a broader parsimonious predicate covering + names, identifiers, codes, and appellations. Engineering identified_by is a + narrower hyponym used when the designation is expressed in operational form. + - >- + SLOT ALIGNMENT: attested_in is a parsimonious hypernym over engineering + has_source and related provenance/documentation slots. + - >- + SLOT ALIGNMENT: grounded_in bridges to engineering derive_from, + has_source, and observe patterns depending on whether the engineering model + expresses derivation, observation target, or source bundle attachment. + - >- + SLOT ALIGNMENT: derived_from_source is the more general provenance bridge to + engineering derive_from and has_source when the source is not modeled as a + discrete observation. + - >- + SLOT ALIGNMENT: realized_through is the broader parsimonious predicate for + process- or activity-based realization. Engineering generated_by is a + narrower hyponym used in operational provenance chains. + - >- + SLOT ALIGNMENT: accessed_under is the parsimonious hypernym for access + conditions, restrictions, rights, and policies. Engineering has_access_policy + is a narrower hyponym within this broader conceptual predicate. + - >- + SLOT ALIGNMENT: marked_as is the broader parsimonious predicate for status or + standing. Engineering has_status is a narrower hyponym carrying operational + state values. + - >- + SLOT ALIGNMENT: located_in is broader than engineering place-related slots such + as located_at, has_location, and locality-bearing reconstruction slots. + - >- + SLOT ALIGNMENT: organized_within and included_in bridge to engineering + encompassed_by and part_of, depending on whether the containment is + organizational, conceptual, or constituent. + - >- + SLOT ALIGNMENT: reconstructs is a parsimonious bridge between activities and + reconstructed entities. In the engineering layer this semantics is often split + across generated_by, generated, or refer_to patterns. + - >- + SLOT ALIGNMENT: situated_in_time is the broader parsimonious temporal + placement predicate. Engineering temporal_extent is a narrower hyponym used + for more explicit time-span modeling. + - >- + SLOT ALIGNMENT: typed_as is a hypernym over engineering has_type and many + narrower enum-backed or type-class-backed patterns. + - >- + SLOT ALIGNMENT: carried_out_by is close to engineering conducted_by and related + provenance slots, but remains intentionally generic in the parsimonious layer. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_type_bridge.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_type_bridge.yaml new file mode 100644 index 0000000000..7e8c035365 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/mappings/parsimony_engineering_type_bridge.yaml @@ -0,0 +1,37 @@ +id: https://nde.nl/ontology/hc/parsimony/mappings/parsimony-engineering-type-bridge +name: parsimony_engineering_type_bridge +title: Parsimonious Type Bridge +description: >- + Bridge from the parsimonious Classification node to the main engineering type + classes, enums, and typing predicates. +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types + - ../classes/Classification + - ../slots/typed_as + - ../../../modules/classes/CustodianType + - ../../../modules/classes/ArchiveOrganizationType + - ../../../modules/enums/AgentTypeEnum + - ../../../modules/slots/has_type +comments: + - >- + TYPE BRIDGE: Classification is the parsimonious hypernym for engineering type + assets modeled as SKOS-like classes, enums, and URI-valued typing slots. + - >- + Classification -> CustodianType is a narrow mapping: the engineering class + carries the detailed custodian taxonomy and hierarchy management. + - >- + Classification -> ArchiveOrganizationType is a further narrow mapping for a + domain-specific branch of the engineering type system. + - >- + Classification -> AgentTypeEnum is a related mapping rather than exact mapping, + because the engineering enum is provenance-scoped and closed-world, while the + parsimonious concept remains open and cross-domain. + - >- + typed_as -> has_type is a close mapping: both express classification, but the + engineering slot supports many specialized aliases, enum-backed values, and + CRM-oriented operational patterns. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/README.md b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/README.md new file mode 100644 index 0000000000..3e902f6ebf --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/README.md @@ -0,0 +1,5 @@ +# Parsimonious slot modules + +This directory will hold the centralized slot definitions for the parsimonious ontology. + +Planned scale: about 30 datatype slots and about 50 object slots. diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/accessed_under.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/accessed_under.yaml new file mode 100644 index 0000000000..d494f3722d --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/accessed_under.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/accessed_under +name: accessed_under +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + dcterms: http://purl.org/dc/terms/ + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + accessed_under: + slot_uri: dcterms:accessRights + description: States the conditions, rights, restrictions, or policy framework under which a resource may be accessed. + range: string + multivalued: true + close_mappings: + - schema:conditionsOfAccess + narrow_mappings: + - hc:has_access_policy diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/attested_in.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/attested_in.yaml new file mode 100644 index 0000000000..304fe4f6ae --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/attested_in.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/attested_in +name: attested_in +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + dcterms: http://purl.org/dc/terms/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + attested_in: + slot_uri: dcterms:source + description: Links an entity, observation, or claim to a source in which it is attested or documented. + range: SourceResource + multivalued: true + close_mappings: + - prov:used + narrow_mappings: + - hc:has_source diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/available_via.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/available_via.yaml new file mode 100644 index 0000000000..f867f89b1e --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/available_via.yaml @@ -0,0 +1,21 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/available_via +name: available_via +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + dcterms: http://purl.org/dc/terms/ + dcat: http://www.w3.org/ns/dcat# +default_prefix: hc +imports: + - linkml:types +slots: + available_via: + slot_uri: schema:url + description: Indicates the page, service, portal, or endpoint through which a resource is made available. + range: uri + multivalued: true + close_mappings: + - dcat:accessURL + related_mappings: + - dcterms:identifier diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/carried_out_by.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/carried_out_by.yaml new file mode 100644 index 0000000000..f484e4ea0a --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/carried_out_by.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/carried_out_by +name: carried_out_by +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + crm: http://www.cidoc-crm.org/cidoc-crm/ +default_prefix: hc +imports: + - linkml:types +slots: + carried_out_by: + slot_uri: prov:wasAssociatedWith + description: Relates an activity or reconstruction to the responsible agent. + range: Agent + multivalued: true + close_mappings: + - crm:P14_carried_out_by + narrow_mappings: + - hc:conducted_by diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/derived_from_source.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/derived_from_source.yaml new file mode 100644 index 0000000000..d4d1f6bf04 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/derived_from_source.yaml @@ -0,0 +1,22 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/derived_from_source +name: derived_from_source +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + dcterms: http://purl.org/dc/terms/ +default_prefix: hc +imports: + - linkml:types +slots: + derived_from_source: + slot_uri: prov:wasDerivedFrom + description: Connects a semantic entity to the source or prior entity from which it is derived. + range: uriorcurie + multivalued: true + broad_mappings: + - prov:wasInfluencedBy + related_mappings: + - dcterms:source + narrow_mappings: + - hc:derive_from diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/designated_by.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/designated_by.yaml new file mode 100644 index 0000000000..ef660a5e68 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/designated_by.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/designated_by +name: designated_by +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + rico: https://www.ica.org/standards/RiC/ontology# +default_prefix: hc +imports: + - linkml:types +slots: + designated_by: + slot_uri: crm:P1_is_identified_by + description: Connects an entity to a name, identifier, code, or appellation by which it is designated. + range: Designation + multivalued: true + close_mappings: + - rico:hasOrHadIdentifier + narrow_mappings: + - hc:identified_by diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/grounded_in.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/grounded_in.yaml new file mode 100644 index 0000000000..6ac57fcc44 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/grounded_in.yaml @@ -0,0 +1,21 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/grounded_in +name: grounded_in +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + grounded_in: + slot_uri: prov:wasDerivedFrom + description: Connects a reconstruction, interpretation, or claim to the evidential basis on which it is grounded. + range: Observation + multivalued: true + broad_mappings: + - prov:wasInfluencedBy + narrow_mappings: + - prov:hadPrimarySource + - hc:derive_from + - hc:observe diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_label_literal.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_label_literal.yaml new file mode 100644 index 0000000000..1f569f3a1c --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_label_literal.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/has_label_literal +name: has_label_literal +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + rdfs: http://www.w3.org/2000/01/rdf-schema# + skos: http://www.w3.org/2004/02/skos/core# + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + has_label_literal: + slot_uri: rdfs:label + description: Primary human-readable label literal for a semantic entity or classification. + range: string + multivalued: true + exact_mappings: + - skos:prefLabel + - schema:name diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_note_literal.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_note_literal.yaml new file mode 100644 index 0000000000..a3d9a02cfd --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_note_literal.yaml @@ -0,0 +1,18 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/has_note_literal +name: has_note_literal +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types +slots: + has_note_literal: + slot_uri: schema:description + description: Free-text note used for concise conceptual documentation. + range: string + multivalued: true + close_mappings: + - skos:note diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_provenance_note.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_provenance_note.yaml new file mode 100644 index 0000000000..68c01e7d3b --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_provenance_note.yaml @@ -0,0 +1,18 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/has_provenance_note +name: has_provenance_note +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# + dcterms: http://purl.org/dc/terms/ +default_prefix: hc +imports: + - linkml:types +slots: + has_provenance_note: + slot_uri: dcterms:provenance + description: Concise provenance note for the parsimonious layer when full provenance structures remain engineering-only. + range: string + multivalued: true + related_mappings: + - prov:wasDerivedFrom diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_uri_literal.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_uri_literal.yaml new file mode 100644 index 0000000000..a75aac31c2 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/has_uri_literal.yaml @@ -0,0 +1,15 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/has_uri_literal +name: has_uri_literal +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + has_uri_literal: + slot_uri: schema:url + description: Canonical URI or web address used to identify or dereference a concept. + range: uri + multivalued: true diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/holds.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/holds.yaml new file mode 100644 index 0000000000..081c2bc11a --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/holds.yaml @@ -0,0 +1,17 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/holds +name: holds +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + rico: https://www.ica.org/standards/RiC/ontology# +default_prefix: hc +imports: + - linkml:types +slots: + holds: + slot_uri: rico:isOrWasHolderOf + description: Relates a custodian or agent concept to a holding concept it holds or held. + range: Holding + multivalued: true + narrow_mappings: + - hc:hold diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/included_in.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/included_in.yaml new file mode 100644 index 0000000000..5f6bd7554a --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/included_in.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/included_in +name: included_in +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + dcterms: http://purl.org/dc/terms/ + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + included_in: + slot_uri: dcterms:isPartOf + description: Relates an entity to a larger whole, set, or framework within which it is included. + range: uriorcurie + multivalued: true + close_mappings: + - schema:isPartOf + narrow_mappings: + - hc:partOf diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/located_in.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/located_in.yaml new file mode 100644 index 0000000000..df17899c13 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/located_in.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/located_in +name: located_in +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + located_in: + slot_uri: schema:location + description: Places a concept or activity in a named place context. + range: PlaceContext + multivalued: true + close_mappings: + - crm:P53_has_former_or_current_location + - prov:atLocation diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/marked_as.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/marked_as.yaml new file mode 100644 index 0000000000..8d0c98623c --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/marked_as.yaml @@ -0,0 +1,19 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/marked_as +name: marked_as +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + marked_as: + slot_uri: hc:hasStatus + description: Marks an entity with a current state, standing, or descriptive status relevant to interpretation or access. + range: string + multivalued: true + related_mappings: + - schema:status + narrow_mappings: + - hc:has_status diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/occurred_on.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/occurred_on.yaml new file mode 100644 index 0000000000..348bc57b02 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/occurred_on.yaml @@ -0,0 +1,19 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/occurred_on +name: occurred_on +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + schema: http://schema.org/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + occurred_on: + slot_uri: schema:startDate + description: Temporal literal used when the parsimonious layer does not yet model time as a separate class. + range: string + close_mappings: + - prov:startedAtTime + related_mappings: + - prov:endedAtTime diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/organized_within.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/organized_within.yaml new file mode 100644 index 0000000000..394cc105cf --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/organized_within.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/organized_within +name: organized_within +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + dcterms: http://purl.org/dc/terms/ + schema: http://schema.org/ +default_prefix: hc +imports: + - linkml:types +slots: + organized_within: + slot_uri: dcterms:isPartOf + description: Relates an organizational concept to the larger institutional structure that contains it. + range: CustodialEntity + multivalued: true + close_mappings: + - schema:isPartOf + narrow_mappings: + - hc:encompassedBy diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/realized_through.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/realized_through.yaml new file mode 100644 index 0000000000..7bc96b7f53 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/realized_through.yaml @@ -0,0 +1,21 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/realized_through +name: realized_through +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + realized_through: + slot_uri: prov:wasGeneratedBy + description: Relates an entity to the activity, process, or reconstruction workflow through which it becomes realized. + range: Activity + multivalued: true + broad_mappings: + - prov:wasInfluencedBy + related_mappings: + - prov:generated + narrow_mappings: + - hc:generated_by diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/reconstructs.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/reconstructs.yaml new file mode 100644 index 0000000000..2d35a5c2c0 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/reconstructs.yaml @@ -0,0 +1,17 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/reconstructs +name: reconstructs +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + reconstructs: + slot_uri: prov:generated + description: Relates a reconstruction activity to the reconstructed conceptual entity it yields. + range: Reconstruction + multivalued: true + related_mappings: + - prov:wasGeneratedBy diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/situated_in_time.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/situated_in_time.yaml new file mode 100644 index 0000000000..3697f15341 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/situated_in_time.yaml @@ -0,0 +1,21 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/situated_in_time +name: situated_in_time +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + prov: http://www.w3.org/ns/prov# +default_prefix: hc +imports: + - linkml:types +slots: + situated_in_time: + slot_uri: crm:P4_has_time-span + description: Places an entity, activity, or relation within a time span, period, or temporal frame. + range: string + multivalued: true + related_mappings: + - prov:startedAtTime + - prov:endedAtTime + narrow_mappings: + - hc:temporal_extent diff --git a/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/typed_as.yaml b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/typed_as.yaml new file mode 100644 index 0000000000..5aeb3afb21 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/modules/slots/typed_as.yaml @@ -0,0 +1,20 @@ +id: https://nde.nl/ontology/hc/parsimony/slot/typed_as +name: typed_as +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types +slots: + typed_as: + slot_uri: rdf:type + description: Relates a concept to a reusable classification or type node. + range: Classification + multivalued: true + related_mappings: + - skos:broader + narrow_mappings: + - hc:has_type diff --git a/frontend/public/schemas/20251121/linkml/parsimony/parsimony_core.yaml b/frontend/public/schemas/20251121/linkml/parsimony/parsimony_core.yaml new file mode 100644 index 0000000000..d0d83d5ea8 --- /dev/null +++ b/frontend/public/schemas/20251121/linkml/parsimony/parsimony_core.yaml @@ -0,0 +1,62 @@ +id: https://nde.nl/ontology/hc/parsimony/core +name: heritage_custodian_parsimony +title: Heritage Custodian Parsimony Ontology +description: >- + Parsimonious conceptual facade over the engineering ontology in ../modules/. + This package keeps a deliberately small class and slot set and explains how + broad conceptual nodes map to richer engineering classes, enums, and slots. +version: 0.1.0 +license: https://creativecommons.org/licenses/by-sa/4.0/ +prefixes: + linkml: https://w3id.org/linkml/ + hc: https://nde.nl/ontology/hc/ + pico: https://personsincontext.org/model# + prov: http://www.w3.org/ns/prov# + schema: http://schema.org/ + crm: http://www.cidoc-crm.org/cidoc-crm/ + rico: https://www.ica.org/standards/RiC/ontology# + skos: http://www.w3.org/2004/02/skos/core# +default_prefix: hc +imports: + - linkml:types + - metadata + - modules/slots/designated_by + - modules/slots/has_label_literal + - modules/slots/has_note_literal + - modules/slots/has_uri_literal + - modules/slots/available_via + - modules/slots/derived_from_source + - modules/slots/realized_through + - modules/slots/accessed_under + - modules/slots/attested_in + - modules/slots/has_provenance_note + - modules/slots/included_in + - modules/slots/marked_as + - modules/slots/occurred_on + - modules/slots/organized_within + - modules/slots/situated_in_time + - modules/slots/carried_out_by + - modules/slots/grounded_in + - modules/slots/holds + - modules/slots/located_in + - modules/slots/reconstructs + - modules/slots/typed_as + - modules/classes/Activity + - modules/classes/Agent + - modules/classes/CustodialEntity + - modules/classes/Holding + - modules/classes/Designation + - modules/classes/Observation + - modules/classes/PlaceContext + - modules/classes/Reconstruction + - modules/classes/SourceResource + - modules/classes/Classification + - modules/mappings/parsimony_engineering_bridge + - modules/mappings/parsimony_engineering_class_alignments + - modules/mappings/parsimony_engineering_slot_alignments + - modules/mappings/parsimony_engineering_type_bridge +comments: + - >- + This schema is intentionally small. Engineering detail remains in + schemas/20251121/linkml/modules/ and must be connected through explicit + mapping files. diff --git a/frontend/scripts/generate-schema-manifest.cjs b/frontend/scripts/generate-schema-manifest.cjs index 8e584198a2..bb9cb4c003 100644 --- a/frontend/scripts/generate-schema-manifest.cjs +++ b/frontend/scripts/generate-schema-manifest.cjs @@ -15,8 +15,7 @@ const fs = require('fs'); const path = require('path'); -const SCHEMAS_DIR = path.join(__dirname, '../public/schemas/20251121/linkml'); -const OUTPUT_FILE = path.join(SCHEMAS_DIR, 'manifest.json'); +const ROOT_SCHEMAS_DIR = path.join(__dirname, '../public/schemas/20251121/linkml'); // Category configuration const CATEGORIES = [ @@ -102,15 +101,15 @@ function scanDirectory(dir, category, relativePath = '', excludeSubdirs = []) { /** * Scan root directory for main schema files */ -function scanMainSchemas() { +function scanMainSchemas(baseDir) { const files = []; - if (!fs.existsSync(SCHEMAS_DIR)) { - console.warn(`Schema directory not found: ${SCHEMAS_DIR}`); + if (!fs.existsSync(baseDir)) { + console.warn(`Schema directory not found: ${baseDir}`); return files; } - const entries = fs.readdirSync(SCHEMAS_DIR, { withFileTypes: true }); + const entries = fs.readdirSync(baseDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isFile() && entry.name.endsWith('.yaml') && !entry.name.includes('.bak')) { @@ -129,8 +128,9 @@ function scanMainSchemas() { /** * Generate the manifest */ -function generateManifest() { - console.log(`Scanning LinkML schemas in: ${SCHEMAS_DIR}`); +function generateManifest(baseDir, schemaRoot) { + const outputFile = path.join(baseDir, 'manifest.json'); + console.log(`Scanning LinkML schemas in: ${baseDir}`); const categories = []; let totalFiles = 0; @@ -141,9 +141,9 @@ function generateManifest() { if (catConfig.name === 'main') { // Special handling for main schemas at root level - files = scanMainSchemas(); + files = scanMainSchemas(baseDir); } else if (catConfig.scan && catConfig.scanPath) { - const scanDir = path.join(SCHEMAS_DIR, catConfig.scanPath); + const scanDir = path.join(baseDir, catConfig.scanPath); files = scanDirectory( scanDir, catConfig.name, @@ -167,27 +167,28 @@ function generateManifest() { const manifest = { generated: new Date().toISOString(), - schemaRoot: '/schemas/20251121/linkml', + schemaRoot, totalFiles, categoryCounts, categories }; // Ensure output directory exists - const outputDir = path.dirname(OUTPUT_FILE); + const outputDir = path.dirname(outputFile); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // Write manifest - fs.writeFileSync(OUTPUT_FILE, JSON.stringify(manifest, null, 2)); + fs.writeFileSync(outputFile, JSON.stringify(manifest, null, 2)); // Print summary console.log(`Generated manifest with ${totalFiles} schema files`); for (const cat of categories) { console.log(` - ${cat.displayName}: ${cat.files.length}`); } - console.log(`Output: ${OUTPUT_FILE}`); + console.log(`Output: ${outputFile}`); } -generateManifest(); +generateManifest(ROOT_SCHEMAS_DIR, '/schemas/20251121/linkml'); +generateManifest(path.join(ROOT_SCHEMAS_DIR, 'parsimony'), '/schemas/20251121/linkml/parsimony'); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a8fdb13723..6ea17efa4a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -107,6 +107,17 @@ const router = createBrowserRouter([ }, ], }, + { + path: '/parsimony', + element: , + errorElement: , + children: [ + { + index: true, + element: withSuspense(LinkMLViewerPage), + }, + ], + }, { path: '/datamap', element: , diff --git a/frontend/src/components/layout/Navigation.tsx b/frontend/src/components/layout/Navigation.tsx index 4449f80612..470f6abf3a 100644 --- a/frontend/src/components/layout/Navigation.tsx +++ b/frontend/src/components/layout/Navigation.tsx @@ -46,7 +46,7 @@ export function Navigation() { // Check if we're on a page where scroll-up should NOT auto-expand header // User must click the small logo to expand on these pages - const isNoAutoExpandPage = location.pathname.startsWith('/conversation') || location.pathname.startsWith('/linkml'); + const isNoAutoExpandPage = location.pathname.startsWith('/conversation') || location.pathname.startsWith('/linkml') || location.pathname.startsWith('/parsimony'); // Detect scrolling from ANY scrollable element on the page // Also detect wheel events on non-scrollable areas @@ -346,7 +346,7 @@ export function Navigation() { {/* Ontology Menu */}