73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
|
|
"""
|
||
|
|
Data models for L3 relation triplets.
|
||
|
|
|
||
|
|
A relation triplet is the fundamental unit of the relation graph:
|
||
|
|
Subject --[Predicate]--> Object
|
||
|
|
|
||
|
|
Each triplet is stored as a markdown file in ``output/relations/``.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from dataclasses import dataclass, field
|
||
|
|
from typing import List, Optional
|
||
|
|
|
||
|
|
|
||
|
|
# Controlled relation vocabulary — maps semantic class to VSM channel
|
||
|
|
RELATION_TYPES = {
|
||
|
|
"enables": "S1 → S1",
|
||
|
|
"constrains": "S1 ← S1",
|
||
|
|
"regulates": "S3 → S1",
|
||
|
|
"is regulated by": "S1 ← S3",
|
||
|
|
"coordinates": "S2",
|
||
|
|
"produces": "S1",
|
||
|
|
"consumes": "S1",
|
||
|
|
"monitors": "S3*",
|
||
|
|
"audits": "S3*",
|
||
|
|
"adapts to": "S4",
|
||
|
|
"anticipates": "S4",
|
||
|
|
"defines": "S5 → any",
|
||
|
|
"is defined by": "any ← S5",
|
||
|
|
"contradicts": "any",
|
||
|
|
"tensions with": "any",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class RelationMeta:
|
||
|
|
"""Structured metadata for a single relation triplet.
|
||
|
|
|
||
|
|
Attributes:
|
||
|
|
slug: Unique identifier, e.g.
|
||
|
|
``division_of_labour--constrains--market_extent``
|
||
|
|
subject: Human-readable title of the subject entity
|
||
|
|
subject_slug: Slug of the subject entity (links to L1)
|
||
|
|
predicate: Human-readable predicate phrase, e.g. "limited by"
|
||
|
|
object: Human-readable title of the object entity
|
||
|
|
object_slug: Slug of the object entity (links to L1)
|
||
|
|
relation_type: Semantic class from the controlled vocabulary
|
||
|
|
vsm_channel: VSM systems involved, e.g. "S1 → S2"
|
||
|
|
evidence: Source text quote or chapter reference
|
||
|
|
feedback_role: Description of role in a feedback loop (if any)
|
||
|
|
source_path: Absolute path to the ``.md`` file
|
||
|
|
"""
|
||
|
|
|
||
|
|
slug: str
|
||
|
|
subject: str
|
||
|
|
subject_slug: str
|
||
|
|
predicate: str
|
||
|
|
object: str
|
||
|
|
object_slug: str
|
||
|
|
relation_type: str
|
||
|
|
vsm_channel: str
|
||
|
|
evidence: str = ""
|
||
|
|
feedback_role: str = ""
|
||
|
|
source_path: str = ""
|
||
|
|
|
||
|
|
@property
|
||
|
|
def is_feedback_member(self) -> bool:
|
||
|
|
"""True if this relation participates in a named feedback loop."""
|
||
|
|
return bool(self.feedback_role.strip())
|
||
|
|
|
||
|
|
def edge(self) -> tuple:
|
||
|
|
"""Return a (subject_slug, object_slug, predicate) edge tuple."""
|
||
|
|
return (self.subject_slug, self.object_slug, self.predicate)
|