feat(infospace): add L3 relation graph with VSM-aware triplets (S2.8)
Implements the L3 relation graph layer — a directed graph of (Subject,
Predicate, Object) triplets annotated with VSM channel codes and feedback
roles. Triplets are authored as markdown files under output/relations/,
parsed into RelationMeta dataclasses, and analysed with networkx.
New modules:
- markitect/infospace/relation_models.py — RelationMeta dataclass +
RELATION_TYPES controlled vocabulary (15 relation classes → VSM codes)
- markitect/infospace/relation_parser.py — parse_relation_file() and
parse_relations_directory()
New schema: examples/infospace-with-history/schemas/relation-schema-v1.0.md
— file naming convention, required sections, controlled vocabulary table
15 seed relation files covering the three core WoN feedback loops:
- Capital Accumulation loop (positive reinforcement, S1/S3)
- Market Price Balancing loop (negative feedback, S2/S3)
- Market Extent mutual dependency (S1/S2)
Plus structural relations: wages regulation, rent residual, price
decomposition, invisible hand coordination
CLI: markitect infospace relations [--entity SLUG] [--vsm FILTER]
[--loops] [--stats]
- Builds directed graph from parsed files
- Detects feedback loops via nx.simple_cycles()
- 6 loops found from 15 seed relations (3 intended + 3 emergent)
- --stats aggregates by VSM system code (strips parentheticals)
Config: InfospaceConfig gains relations_dir (default output/relations)
infospace.yaml: schemas.relation references relation-schema-v1.0.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
72
markitect/infospace/relation_models.py
Normal file
72
markitect/infospace/relation_models.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user