""" 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)