Complete source 6 engineering workflows and preserve release validation evidence

This commit is contained in:
Codex
2026-09-06 21:49:04 -07:00
parent 2b2d2bc18b
commit 4b6b5fc197
290 changed files with 48271 additions and 1791 deletions
+46 -3
View File
@@ -6,6 +6,7 @@ use std::collections::BTreeSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tool {
Interaction,
CommunicationMean,
FunctionalExchange,
BoundaryExchange,
}
@@ -13,7 +14,7 @@ pub enum Tool {
impl Tool {
pub fn for_layer(layer: Layer) -> &'static [Self] {
match layer {
Layer::Oa => &[Self::Interaction],
Layer::Oa => &[Self::Interaction, Self::CommunicationMean],
Layer::Sa => &[Self::FunctionalExchange, Self::BoundaryExchange],
}
}
@@ -21,6 +22,7 @@ impl Tool {
pub fn label(self) -> &'static str {
match self {
Self::Interaction => "Interaction",
Self::CommunicationMean => "Communication means",
Self::FunctionalExchange => "Functional exchange",
Self::BoundaryExchange => "Boundary exchange",
}
@@ -29,6 +31,9 @@ impl Tool {
pub fn hint(self) -> &'static str {
match self {
Self::Interaction => "Click a source activity, then a target activity.",
Self::CommunicationMean => {
"Click an operational entity or actor, then another participant. Communication is bidirectional unless you change its orientation."
}
Self::FunctionalExchange => {
"Click an output port or source function, then an input port or target function. Function cards use automatic ports."
}
@@ -40,6 +45,9 @@ impl Tool {
pub fn can_start(self, project: &Project, source: Id) -> bool {
match self {
Self::CommunicationMean => project.elements.get(&source).is_some_and(|e| {
e.layer() == Layer::Oa && matches!(e.kind(), Kind::Entity | Kind::Actor)
}),
Self::Interaction => project
.elements
.get(&source)
@@ -57,6 +65,9 @@ impl Tool {
return false;
}
match self {
Self::CommunicationMean => {
validation::can_connect(project, RelationKind::CommunicationMean, source, target)
}
Self::Interaction => {
validation::can_connect(project, RelationKind::Interaction, source, target)
}
@@ -129,6 +140,9 @@ impl Tool {
}
let name = engineering_name(project, self, source, target);
let body = match self {
Self::CommunicationMean => {
RelationBody::new(RelationKind::CommunicationMean, source, target)
}
Self::Interaction => RelationBody::new(RelationKind::Interaction, source, target),
Self::BoundaryExchange => RelationBody::BoundaryExchange {
source,
@@ -210,7 +224,9 @@ fn engineering_name(project: &Project, tool: Tool, source: Id, target: Id) -> St
project.named(id).to_owned()
}
};
let arrow = if tool == Tool::BoundaryExchange && !boundary_oriented(project, source) {
let arrow = if tool == Tool::CommunicationMean
|| (tool == Tool::BoundaryExchange && !boundary_oriented(project, source))
{
"—"
} else {
"→"
@@ -273,7 +289,10 @@ mod tests {
let actor = element(&mut p, Kind::Actor, Layer::Oa, "Dispatcher");
let function = element(&mut p, Kind::Function, Layer::Sa, "Assess report");
let before = p.clone();
assert_eq!(Tool::for_layer(Layer::Oa), &[Tool::Interaction]);
assert_eq!(
Tool::for_layer(Layer::Oa),
&[Tool::Interaction, Tool::CommunicationMean]
);
assert_eq!(
Tool::Interaction.targets(&p, source),
BTreeSet::from([target])
@@ -289,6 +308,27 @@ mod tests {
assert_eq!(p, before);
}
#[test]
fn operational_communication_uses_participants_without_creating_ports() {
let mut p = Project::empty();
let a = element(&mut p, Kind::Entity, Layer::Oa, "Field team");
let b = element(&mut p, Kind::Actor, Layer::Oa, "Coordinator");
let activity = element(&mut p, Kind::Activity, Layer::Oa, "Report");
let sa = element(&mut p, Kind::System, Layer::Sa, "Controller");
let before = p.clone();
assert_eq!(Tool::CommunicationMean.targets(&p, a), BTreeSet::from([b]));
for invalid in [a, activity, sa, Id::new_v4()] {
assert!(Tool::CommunicationMean.command(&p, a, invalid).is_err());
}
let command = Tool::CommunicationMean.command(&p, a, b).unwrap();
let (accepted, relation) = created(&p, &command);
assert!(matches!(relation.body, RelationBody::CommunicationMean {
source, target, oriented: false, ref items,
} if source == a && target == b && items.is_empty()));
assert_eq!(accepted.elements, p.elements);
assert_eq!(p, before);
}
#[test]
fn explicit_function_ports_keep_owners_contracts_and_do_not_invent_carried_items() {
let mut p = Project::empty();
@@ -532,6 +572,8 @@ mod tests {
let mut p = Project::empty();
let oa_a = element(&mut p, Kind::Activity, Layer::Oa, "Detect incident");
let oa_b = element(&mut p, Kind::Activity, Layer::Oa, "Assess incident");
let oa_team = element(&mut p, Kind::Entity, Layer::Oa, "Response team");
let oa_actor = element(&mut p, Kind::Actor, Layer::Oa, "Dispatcher");
let sa_a = element(&mut p, Kind::Function, Layer::Sa, "Detect report");
let sa_b = element(&mut p, Kind::Function, Layer::Sa, "Assess report");
let system = element(&mut p, Kind::System, Layer::Sa, "System");
@@ -547,6 +589,7 @@ mod tests {
let mut document = Document::from_bundle(bundle, ProjectLimits::default()).unwrap();
for (tool, source, target) in [
(Tool::Interaction, oa_a, oa_b),
(Tool::CommunicationMean, oa_team, oa_actor),
(Tool::FunctionalExchange, sa_a, sa_b),
(Tool::BoundaryExchange, boundary_a, boundary_b),
] {