MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / validate_intent

Function validate_intent

atomic-canonical/src/gate.rs:70–163  ·  view source on GitHub ↗

Validate a canonical Intent node against `IntentShape` (+ sub-shapes).

(node: &CanonicalNode)

Source from the content-addressed store, hash-verified

68
69/// Validate a canonical Intent node against `IntentShape` (+ sub-shapes).
70pub fn validate_intent(node: &CanonicalNode) -> ValidationReport {
71 let mut out = Vec::new();
72 let focus = &node.id;
73
74 // status ∈ closed set, exactly one (it is a single field, so cardinality holds).
75 if !vocab::is_known_intent_status(&node.status) {
76 out.push(Violation {
77 focus_node: focus.clone(),
78 shape: "IntentShape".into(),
79 path: Some("status".into()),
80 message: format!(
81 "status '{}' is not one of {:?}",
82 node.status,
83 vocab::INTENT_STATUS
84 ),
85 });
86 }
87
88 // attributedTo must be present (sh:class prov:Agent deferred — see M0 notes).
89 if node.attributed_to.as_deref().unwrap_or("").is_empty() {
90 out.push(Violation {
91 focus_node: focus.clone(),
92 shape: "IntentShape".into(),
93 path: Some("attributedTo".into()),
94 message: "author (attributedTo) must be present as a DID".into(),
95 });
96 }
97
98 // proof must be present.
99 if node.proof.is_none() {
100 out.push(Violation {
101 focus_node: focus.clone(),
102 shape: "IntentShape".into(),
103 path: Some("proof".into()),
104 message: "intent must carry a Data Integrity proof".into(),
105 });
106 }
107
108 // presence-enforced: a reason must exist (content left honest).
109 match &node.why {
110 Some(w) if !w.trim().is_empty() => {}
111 _ => out.push(Violation {
112 focus_node: focus.clone(),
113 shape: "IntentShape".into(),
114 path: Some("why".into()),
115 message: "a reason (why) must be present — its content is not graded".into(),
116 }),
117 }
118
119 // Scope-out presence: if scope is being declared (scope-in present), the
120 // intent must also state what is out of scope — the boundaries the agent
121 // must respect. This is presence-enforced (we never read the prose). An
122 // intent with no scope section at all is not forced to declare scope-out.
123 if !node.has_scope_in.is_empty() && node.has_scope_out.is_empty() {
124 out.push(Violation {
125 focus_node: focus.clone(),
126 shape: "IntentShape".into(),
127 path: Some("hasScopeOut".into()),

Calls 6

is_known_intent_statusFunction · 0.85
is_known_ac_statusFunction · 0.85
is_noneMethod · 0.80
pushMethod · 0.45
cloneMethod · 0.45
is_emptyMethod · 0.45