Skip to main content

stoa_core/
relationship.rs

1//! Typed relationships + entity-type vocabulary (ARCHITECTURE §5).
2
3use serde::{Deserialize, Serialize};
4
5/// Entity type defaults (ARCHITECTURE §5 — "Entity types"). The schema
6/// (`STOA.md`) may extend this vocabulary per workspace.
7pub const DEFAULT_ENTITY_TYPES: &[&str] = &[
8    "person", "project", "library", "service", "tool", "file", "decision", "concept",
9];
10
11/// Relationship type defaults (ARCHITECTURE §5 — "Relationship types").
12pub const DEFAULT_RELATIONSHIP_TYPES: &[&str] = &[
13    "uses",
14    "depends_on",
15    "instance_of",
16    "caused",
17    "fixed",
18    "supersedes",
19    "contradicts",
20    "cites",
21    "mentions",
22];
23
24/// Wrapper around an entity-type string. Strings are kept open so workspaces
25/// can extend the vocabulary in `STOA.md`; validation against the active
26/// schema is the caller's job (see `validate::validate_page`).
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28#[serde(transparent)]
29pub struct EntityType(pub String);
30
31impl EntityType {
32    /// Borrow the inner string.
33    #[must_use]
34    pub fn as_str(&self) -> &str {
35        &self.0
36    }
37}
38
39impl std::fmt::Display for EntityType {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        f.write_str(&self.0)
42    }
43}
44
45/// Wrapper around a relationship-type string. Stored as a plain string for
46/// the same reason as [`EntityType`] — schemas can extend the vocabulary.
47#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
48#[serde(transparent)]
49pub struct RelationshipType(pub String);
50
51impl RelationshipType {
52    /// Borrow the inner string.
53    #[must_use]
54    pub fn as_str(&self) -> &str {
55        &self.0
56    }
57}
58
59impl std::fmt::Display for RelationshipType {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        f.write_str(&self.0)
62    }
63}
64
65/// A typed relationship between two pages (ARCHITECTURE §2 + §5).
66///
67/// Confidence + source provenance are optional — they're populated by the
68/// LLM/extractor and absent on hand-authored pages.
69#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
70pub struct Relationship {
71    /// Relationship kind, validated against the schema vocabulary.
72    #[serde(rename = "type")]
73    pub kind: RelationshipType,
74    /// Page id (`ent-*`, `con-*`, `syn-*`) this relationship points at.
75    pub target: String,
76    /// Optional 0.0..=1.0 numeric confidence (ARCHITECTURE §4.3).
77    #[serde(default, skip_serializing_if = "Option::is_none")]
78    pub confidence: Option<f64>,
79    /// Optional supporting source paths (typically under `raw/`).
80    #[serde(default, skip_serializing_if = "Vec::is_empty")]
81    pub sources: Vec<String>,
82}