Skip to content

Commit bdbe9e4

Browse files
committed
minor reware so evidence prior to determination is anchored
1 parent 6725d26 commit bdbe9e4

8 files changed

Lines changed: 54 additions & 31 deletions

File tree

__marimo__/session/notebook.py.json

Lines changed: 7 additions & 7 deletions
Large diffs are not rendered by default.

evidence/binding.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
"""Bind computational evidence to the RDF traceability graph.
22
3-
Creates rtm:Evidence nodes (ProofArtifact, SimulationResult) linked to the
4-
computational activities that produced them via PROV-O. Evidence is NOT
5-
linked directly to requirements — only attestation does that.
3+
Creates rtm:Evidence nodes (ProofArtifact, SimulationResult) linked to:
4+
- The computational activity that produced them (prov:wasGeneratedBy)
5+
- The requirement they address (rtm:addresses) — structural intent, not judgment
6+
7+
Evidence *addresses* a requirement but does not *satisfy* it.
8+
Only human attestation (rtm:attests) connects evidence to satisfaction.
69
"""
710

811
from __future__ import annotations
@@ -41,6 +44,7 @@ def bind_proof_evidence(
4144
graph.add((ev_uri, RTM.proofHash, Literal(proof_hash)))
4245
graph.add((ev_uri, RTM.resultSummary, Literal(result_summary)))
4346
graph.add((ev_uri, RTM.evidenceMethod, RTM.FormalProof))
47+
graph.add((ev_uri, RTM.addresses, ADCS[requirement_id]))
4448
graph.add((ev_uri, PROV.wasGeneratedBy, act_uri))
4549
graph.add((ev_uri, PROV.generatedAtTime, Literal(
4650
datetime.now(timezone.utc).isoformat(), datatype=XSD.dateTime,
@@ -83,6 +87,7 @@ def bind_simulation_evidence(
8387
graph.add((ev_uri, RTM.modelHash, Literal(model_hash)))
8488
graph.add((ev_uri, RTM.resultSummary, Literal(result_summary)))
8589
graph.add((ev_uri, RTM.evidenceMethod, RTM.Simulation))
90+
graph.add((ev_uri, RTM.addresses, ADCS[requirement_id]))
8691
graph.add((ev_uri, PROV.wasGeneratedBy, act_uri))
8792
graph.add((ev_uri, PROV.generatedAtTime, Literal(
8893
datetime.now(timezone.utc).isoformat(), datatype=XSD.dateTime,

interrogate/explain.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ def explain_requirement(graph: Graph, req_name: str) -> str:
7474
?ev a ?type ;
7575
rtm:contentHash ?hash ;
7676
rtm:resultSummary ?summary ;
77-
prov:wasGeneratedBy ?activity .
78-
?activity prov:used ?req .
77+
rtm:addresses ?req .
7978
?req sysml:declaredName "{req_name}" .
8079
FILTER(?type IN (rtm:ProofArtifact, rtm:SimulationResult))
8180
OPTIONAL {{ ?ev rtm:proofHash ?proofHash }}

interrogate/visualize.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,12 @@ def _extract_graph_data(rdf_graph: Graph) -> tuple[nx.DiGraph, dict, dict]:
120120
for row in query_to_dicts(rdf_graph, q):
121121
G.add_edge(row["reqName"], row["elementName"], rel="satisfiedBy")
122122

123-
# --- Evidence nodes ---
123+
# --- Evidence nodes (linked via rtm:addresses) ---
124124
q = """
125125
SELECT ?ev ?type ?hash ?reqName WHERE {
126126
?ev a ?type ;
127127
rtm:contentHash ?hash ;
128-
prov:wasGeneratedBy ?act .
129-
?act prov:used ?req .
128+
rtm:addresses ?req .
130129
?req sysml:declaredName ?reqName .
131130
FILTER(?type IN (rtm:ProofArtifact, rtm:SimulationResult))
132131
}
@@ -142,7 +141,7 @@ def _extract_graph_data(rdf_graph: Graph) -> tuple[nx.DiGraph, dict, dict]:
142141
G.add_node(node_id, label=label)
143142
node_colors[node_id] = color
144143
node_types[node_id] = "evidence"
145-
G.add_edge(row["reqName"], node_id, rel="evidence")
144+
G.add_edge(row["reqName"], node_id, rel="addresses")
146145

147146
# --- Attestation nodes ---
148147
q = """
@@ -261,7 +260,7 @@ def _hierarchical_layout(
261260
ev_nodes = sorted([n for n, t in node_types.items() if t == "evidence"])
262261
ev_req_map: dict[str, str] = {}
263262
for u, v, data in G.edges(data=True):
264-
if data.get("rel") == "evidence" and v in ev_nodes:
263+
if data.get("rel") == "addresses" and v in ev_nodes:
265264
ev_req_map[v] = u
266265

267266
# Group evidence by requirement, then stack vertically near that requirement
@@ -300,7 +299,7 @@ def build_rtm_figure(
300299
edge_styles = {
301300
"derivedFrom": {"style": "solid", "color": "#888888", "width": 1.5},
302301
"satisfiedBy": {"style": "solid", "color": "#555555", "width": 1.5},
303-
"evidence": {"style": "dashed", "color": "#999999", "width": 1.0},
302+
"addresses": {"style": "dashed", "color": "#999999", "width": 1.0},
304303
"attests": {"style": "solid", "color": COLORS["attestation"], "width": 2.0},
305304
}
306305

notebook.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,12 @@ def __(mo):
459459
to the structural model version), and PROV-O provenance (who/what
460460
produced it, when).
461461
462-
Evidence is **not linked directly to requirements**. It floats in the
463-
graph, waiting for a human to judge its sufficiency.
462+
Each evidence artifact **addresses** a specific requirement — recording
463+
the structural intent that "this proof was constructed to evaluate
464+
REQ-003." But `rtm:addresses` is not `rtm:attests`. The evidence
465+
says *what was analyzed*; only human attestation says *whether it's
466+
sufficient*. An evidence artifact can address a requirement and still
467+
lead to a declined attestation — as we'll see with REQ-001.
464468
""")
465469
return
466470

ontology/rtm.ttl

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ rtm: a owl:Ontology ;
2020
and attestation concepts needed to close the traceability loop.
2121
2222
Core epistemological principle: computational evidence does not verify
23-
requirements. Evidence supports a human judgment (attestation) that
24-
requirements are satisfied. Models are imperfect representations;
23+
requirements. Evidence *addresses* a requirement (structural intent)
24+
but only human attestation connects evidence to requirement
25+
*satisfaction* (judgment). Models are imperfect representations;
2526
the engineer judges model adequacy and evidence sufficiency.""" ;
2627
owl:imports <http://www.w3.org/ns/prov#> .
2728

@@ -126,6 +127,25 @@ rtm:attestedBy a owl:ObjectProperty ;
126127
rdfs:comment "Inverse of rtm:attests." ;
127128
owl:inverseOf rtm:attests .
128129

130+
rtm:addresses a owl:ObjectProperty ;
131+
rdfs:domain rtm:Evidence ;
132+
rdfs:range sysml:RequirementDefinition ;
133+
rdfs:label "addresses" ;
134+
rdfs:comment """Structural link from evidence to the requirement it was
135+
produced to evaluate. This is NOT an attestation — it records
136+
intent ('this proof was constructed to address REQ-003'), not
137+
judgment ('this proof is sufficient to satisfy REQ-003').
138+
The human attestation resolves whether addressed evidence is
139+
sufficient.""" ;
140+
owl:inverseOf rtm:addressedBy .
141+
142+
rtm:addressedBy a owl:ObjectProperty ;
143+
rdfs:domain sysml:RequirementDefinition ;
144+
rdfs:range rtm:Evidence ;
145+
rdfs:label "addressed by" ;
146+
rdfs:comment "Inverse of rtm:addresses." ;
147+
owl:inverseOf rtm:addresses .
148+
129149
rtm:hasEvidence a owl:ObjectProperty ;
130150
rdfs:domain rtm:Attestation ;
131151
rdfs:range rtm:Evidence ;

traceability/queries.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,10 @@
5353
# ---------------------------------------------------------------------------
5454

5555
ALL_EVIDENCE = """
56-
SELECT ?ev ?type ?method ?hash ?summary ?activity WHERE {
56+
SELECT ?ev ?type ?method ?hash ?summary WHERE {
5757
?ev a ?type ;
5858
rtm:contentHash ?hash ;
59-
rtm:resultSummary ?summary ;
60-
prov:wasGeneratedBy ?activity .
59+
rtm:resultSummary ?summary .
6160
OPTIONAL { ?ev rtm:evidenceMethod ?method }
6261
FILTER(?type IN (rtm:ProofArtifact, rtm:SimulationResult))
6362
}
@@ -69,8 +68,7 @@
6968
?ev a ?type ;
7069
rtm:contentHash ?hash ;
7170
rtm:resultSummary ?summary ;
72-
prov:wasGeneratedBy ?activity .
73-
?activity prov:used ?req .
71+
rtm:addresses ?req .
7472
?req sysml:declaredName ?reqName .
7573
FILTER(?type IN (rtm:ProofArtifact, rtm:SimulationResult))
7674
FILTER(?reqName = "%s")
@@ -141,8 +139,7 @@
141139
?ev a ?evType ;
142140
rtm:contentHash ?evHash ;
143141
rtm:resultSummary ?evSummary ;
144-
prov:wasGeneratedBy ?activity .
145-
?activity prov:used ?req .
142+
rtm:addresses ?req .
146143
FILTER(?evType IN (rtm:ProofArtifact, rtm:SimulationResult))
147144
}
148145
OPTIONAL {

traceability/rtm.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ def validate_evidence_completeness(graph: Graph) -> list[str]:
8686
name = req["name"]
8787
q = f"""
8888
SELECT (COUNT(?ev) AS ?cnt) WHERE {{
89-
?ev prov:wasGeneratedBy ?act .
90-
?act prov:used ?req .
89+
?ev rtm:addresses ?req .
9190
?req sysml:declaredName "{name}" .
9291
}}
9392
"""

0 commit comments

Comments
 (0)