2727 "scripts/validate_philosophy_graph_projection.py" ,
2828 "tests/test_philosophy_graph_projection.py" ,
2929)
30+ PREDICATE_GRAPH_LAYERS = {
31+ "belongs_to_genre" : {"conceptual-relation" },
32+ "canonized_by" : {"canonical-relation" , "transmission-relation" },
33+ "commented_by" : {"transmission-relation" },
34+ "contested_by" : {"conceptual-relation" , "evidence-relation" },
35+ "contains_dossier" : {"source-relation" },
36+ "contains_row" : {"source-relation" },
37+ "contains_table" : {"source-relation" },
38+ "contains_view" : {"source-relation" },
39+ "develops_concept" : {"conceptual-relation" },
40+ "figure_anchor" : {"historical-relation" , "source-relation" },
41+ "fragments_preserved_by" : {"evidence-relation" , "transmission-relation" },
42+ "has_atlas" : {"source-relation" },
43+ "has_candidate_node" : {"candidate-relation" },
44+ "has_node_type_pressure" : {"candidate-relation" , "evidence-relation" },
45+ "has_prepared_dossier" : {"evidence-relation" , "source-relation" },
46+ "has_relation_pressure" : {"candidate-relation" , "evidence-relation" },
47+ "has_section" : {"source-relation" },
48+ "has_view_section" : {"source-relation" },
49+ "influences" : {"conceptual-relation" , "historical-relation" },
50+ "institutionalized_in" : {"historical-relation" },
51+ "polemicizes_with" : {"conceptual-relation" , "evidence-relation" },
52+ "preserved_in" : {"evidence-relation" , "transmission-relation" },
53+ "preserves_in" : {"evidence-relation" , "transmission-relation" },
54+ "receives_from" : {"transmission-relation" },
55+ "survives_as" : {"evidence-relation" , "historical-relation" , "transmission-relation" },
56+ "translated_into" : {"transmission-relation" },
57+ "transforms_concept" : {"conceptual-relation" },
58+ "transmits_to" : {"transmission-relation" },
59+ "uncertain_relation" : {"evidence-relation" },
60+ "uses_language" : {"source-relation" },
61+ "uses_script" : {"source-relation" },
62+ }
63+ NODE_TYPE_GRAPH_LAYERS = {
64+ "atlas" : {"source-relation" },
65+ "atlas-node-type" : {"source-relation" },
66+ "atlas-relation-kind" : {"source-relation" },
67+ "atlas-section" : {"source-relation" },
68+ "candidate-endpoint" : {"candidate-relation" , "evidence-relation" },
69+ "candidate-node" : {"candidate-relation" },
70+ "domain-root" : {"source-relation" },
71+ "graph-view" : {"source-relation" },
72+ "master-table" : {"source-relation" },
73+ "master-table-row" : {"historical-relation" , "source-relation" },
74+ "prepared-dossier" : {"evidence-relation" , "source-relation" },
75+ "view-section" : {"source-relation" },
76+ }
77+ KNOWN_GRAPH_LAYERS = {
78+ "source-relation" ,
79+ "historical-relation" ,
80+ "conceptual-relation" ,
81+ "transmission-relation" ,
82+ "evidence-relation" ,
83+ "candidate-relation" ,
84+ "canonical-relation" ,
85+ }
3086
3187
3288def repo_ref (path : Path ) -> str :
@@ -59,6 +115,35 @@ def _as_string_set(values: Any) -> set[str]:
59115 return {str (item ) for item in values if isinstance (item , str ) and item }
60116
61117
118+ def _node_semantic_layers (node : dict [str , Any ]) -> set [str ]:
119+ layers = set (NODE_TYPE_GRAPH_LAYERS .get (str (node .get ("node_type" ) or "" ), {"source-relation" }))
120+ properties = node .get ("properties" )
121+ if isinstance (properties , dict ):
122+ if str (properties .get ("canon_status" ) or "" ) == "pre-canon" :
123+ layers .add ("candidate-relation" )
124+ if str (properties .get ("authority_posture" ) or "" ).endswith ("_candidate" ):
125+ layers .add ("candidate-relation" )
126+ if str (properties .get ("priority" ) or "" ).strip ():
127+ layers .add ("evidence-relation" )
128+ return layers & KNOWN_GRAPH_LAYERS
129+
130+
131+ def _edge_semantic_layers (edge : dict [str , Any ]) -> set [str ]:
132+ predicate = str (edge .get ("predicate_id" ) or "" )
133+ layers = set (PREDICATE_GRAPH_LAYERS .get (predicate , {"source-relation" }))
134+ properties = edge .get ("properties" )
135+ if isinstance (properties , dict ):
136+ if str (properties .get ("canon_status" ) or "" ) == "pre-canon" :
137+ layers .add ("candidate-relation" )
138+ if str (properties .get ("authority_posture" ) or "" ).endswith ("_candidate" ):
139+ layers .add ("candidate-relation" )
140+ if str (properties .get ("endpoint_resolution" ) or "" ) == "unresolved" :
141+ layers .add ("evidence-relation" )
142+ if str (properties .get ("confidence" ) or "" ) in {"низкий" , "low" }:
143+ layers .add ("evidence-relation" )
144+ return layers & KNOWN_GRAPH_LAYERS
145+
146+
62147def _node_matches_filters (node : dict [str , Any ], filters : dict [str , Any ]) -> bool :
63148 node_type = str (node .get ("node_type" ) or "" )
64149 label = str (node .get ("label" ) or "" )
@@ -704,16 +789,29 @@ def build_payload() -> dict[str, Any]:
704789 view_id = str (view .get ("view_id" ) or "" )
705790 graph_layers = _as_string_set (view .get ("graph_layers" ))
706791 view_nodes , view_edges , view_diagnostics = _pick_view_material (view , atlas_nodes_by_id , atlas_edges )
792+ view_node_layers : dict [str , set [str ]] = {
793+ str (node ["node_id" ]): _node_semantic_layers (node )
794+ for node in view_nodes
795+ }
796+ view_edge_layers : dict [str , set [str ]] = {}
797+ for edge in view_edges :
798+ edge_id = str (edge ["edge_id" ])
799+ edge_layers = _edge_semantic_layers (edge )
800+ view_edge_layers [edge_id ] = edge_layers
801+ for endpoint_key in ("from_id" , "to_id" ):
802+ endpoint_id = str (edge .get (endpoint_key ) or "" )
803+ if endpoint_id in view_node_layers :
804+ view_node_layers [endpoint_id ].update (edge_layers )
707805 for node in view_nodes :
708806 node_id = str (node ["node_id" ])
709807 membership = node_membership .setdefault (node_id , {"view_ids" : set (), "graph_layers" : set ()})
710808 membership ["view_ids" ].add (view_id )
711- membership ["graph_layers" ].update (graph_layers )
809+ membership ["graph_layers" ].update (view_node_layers . get ( node_id ) or _node_semantic_layers ( node ) )
712810 for edge in view_edges :
713811 edge_id = str (edge ["edge_id" ])
714812 membership = edge_membership .setdefault (edge_id , {"view_ids" : set (), "graph_layers" : set ()})
715813 membership ["view_ids" ].add (view_id )
716- membership ["graph_layers" ].update (graph_layers )
814+ membership ["graph_layers" ].update (view_edge_layers . get ( edge_id ) or _edge_semantic_layers ( edge ) )
717815 diagnostics .extend (view_diagnostics )
718816 views .append (
719817 {
@@ -736,15 +834,15 @@ def build_payload() -> dict[str, Any]:
736834 _projection_node (
737835 node ,
738836 view_ids = {view_id },
739- graph_layers = graph_layers ,
837+ graph_layers = view_node_layers . get ( str ( node [ "node_id" ])) or _node_semantic_layers ( node ) ,
740838 )
741839 for node in view_nodes
742840 ],
743841 "edges" : [
744842 _projection_edge (
745843 edge ,
746844 view_ids = {view_id },
747- graph_layers = graph_layers ,
845+ graph_layers = view_edge_layers . get ( str ( edge [ "edge_id" ])) or _edge_semantic_layers ( edge ) ,
748846 )
749847 for edge in view_edges
750848 ],
0 commit comments