1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! [`AgenticSystemAnalysis`] — one pass over a design, against the
//! ceremonies that are actually published.
//!
//! The analysis is the only thing standing between a design somebody
//! wrote and a run that would discover its defects one stall at a
//! time. It therefore collects every finding rather than stopping at
//! the first, and every finding names the element it is about, so an
//! author — human or agent — can fix a design in one pass.
//!
//! It resolves nothing itself. The pins are looked up by the
//! application through the publication port and handed in, so the
//! domain stays a function of what it was given.
use std::collections::BTreeMap;
use crate::value_objects::SystemCeremonyId;
use super::{
AgenticSystem, AgenticSystemParts, AgenticSystemValidationReport, PublishedCeremonyDefinition,
};
mod capabilities;
mod compositions;
mod dependencies;
mod independence;
mod references;
/// A design, the published definitions it pinned, and the checks that
/// compare them.
#[derive(Debug, Clone, Copy)]
pub struct AgenticSystemAnalysis<'design> {
parts: AgenticSystemParts<'design>,
resolved: &'design BTreeMap<SystemCeremonyId, PublishedCeremonyDefinition>,
}
impl<'design> AgenticSystemAnalysis<'design> {
#[must_use]
pub fn of(
design: &'design AgenticSystem,
resolved: &'design BTreeMap<SystemCeremonyId, PublishedCeremonyDefinition>,
) -> Self {
Self {
parts: AgenticSystemParts::of(design),
resolved,
}
}
/// Every defect, in check order.
///
/// References first, because a check that reasoned about a name
/// nothing declares would produce a second finding about the same
/// mistake in a vocabulary the author never used.
#[must_use]
pub fn report(&self) -> AgenticSystemValidationReport {
let mut findings = Vec::new();
references::collect(self.parts, &mut findings);
dependencies::collect(self.parts, &mut findings);
compositions::collect(self.parts, self.resolved, &mut findings);
capabilities::collect(self.parts, &mut findings);
independence::collect(self.parts, &mut findings);
AgenticSystemValidationReport::new(
findings,
self.resolved.iter().map(|(ceremony, published)| {
(
ceremony.clone(),
crate::value_objects::DefinitionPin::new(
published.name().clone(),
published.version().clone(),
published.digest(),
),
)
}),
)
}
}
impl AgenticSystem {
/// Analyse this design against the definitions its pins resolved
/// to.
#[must_use]
pub fn analyze(
&self,
resolved: &BTreeMap<SystemCeremonyId, PublishedCeremonyDefinition>,
) -> AgenticSystemValidationReport {
AgenticSystemAnalysis::of(self, resolved).report()
}
}