Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s
Preserve current core, source, REST, desktop, recovery, documentation and validation work, including AGENTS.md and the development summary. This is a work-in-progress checkpoint: the new compact palette has outstanding compilation errors and native acceptance; earlier passing gates retain their documented scope.
762 lines
20 KiB
Rust
762 lines
20 KiB
Rust
use crate::*;
|
|
use std::collections::BTreeMap;
|
|
fn add(p: &mut Project, kind: Kind, layer: Layer, name: &str, parent: Option<Id>) -> Id {
|
|
p.add_element(kind, layer, name, parent).unwrap()
|
|
}
|
|
fn occurrence(
|
|
p: &mut Project,
|
|
owner: Id,
|
|
layer: Layer,
|
|
name: &str,
|
|
exchange: Id,
|
|
sender: Option<Id>,
|
|
receiver: Option<Id>,
|
|
) -> Id {
|
|
let id = add(p, Kind::Occurrence, layer, name, Some(owner));
|
|
*p.elements.get_mut(&id).unwrap().shared_mut().unwrap() = SharedBody::Occurrence {
|
|
body: OccurrenceBody::Exchange {
|
|
operation: None,
|
|
exchange: Some(exchange),
|
|
sender,
|
|
receiver,
|
|
message_kind: MessageKind::Asynchronous,
|
|
reply_to: None,
|
|
values: vec![],
|
|
},
|
|
precondition: String::new(),
|
|
postcondition: String::new(),
|
|
};
|
|
p.elements
|
|
.get_mut(&owner)
|
|
.unwrap()
|
|
.steps_mut()
|
|
.unwrap()
|
|
.push(id);
|
|
id
|
|
}
|
|
fn port(p: &mut Project, owner: Id, name: &str, direction: PortDirection, interface: Id) -> Id {
|
|
let items = crate::data::interface_items(p, interface);
|
|
let contract = if p.elements[&owner].kind() == Kind::Function {
|
|
if direction == PortDirection::Out {
|
|
PortContract::FunctionOutput {
|
|
outgoing_items: items,
|
|
}
|
|
} else {
|
|
PortContract::FunctionInput {
|
|
incoming_items: items,
|
|
}
|
|
}
|
|
} else {
|
|
PortContract::Component {
|
|
kind: ComponentPortKind::Flow,
|
|
orientation: match direction {
|
|
PortDirection::In => ComponentPortOrientation::In,
|
|
PortDirection::Out => ComponentPortOrientation::Out,
|
|
PortDirection::InOut => ComponentPortOrientation::InOut,
|
|
},
|
|
}
|
|
};
|
|
let id = Id::new_v4();
|
|
let element = crate::ports::make_port(p, id, owner, name, contract).unwrap();
|
|
p.elements.insert(id, element);
|
|
id
|
|
}
|
|
fn diagram(
|
|
p: &mut Project,
|
|
layer: Layer,
|
|
projection: ProjectionKind,
|
|
name: &str,
|
|
elements: &[Id],
|
|
) -> Id {
|
|
let id = Id::new_v4();
|
|
let alias = p.fresh_alias(name, "diagram", id);
|
|
p.diagrams.insert(
|
|
id,
|
|
Diagram {
|
|
id,
|
|
alias,
|
|
name: name.into(),
|
|
description: "A focused projection of the shared engineering model.".into(),
|
|
layer,
|
|
projection,
|
|
view_options: Default::default(),
|
|
nodes: BTreeMap::new(),
|
|
routes: vec![],
|
|
},
|
|
);
|
|
for (index, e) in elements.iter().enumerate() {
|
|
p.place(
|
|
id,
|
|
*e,
|
|
Position {
|
|
x: 60. + (index % 4) as f32 * 280.,
|
|
y: 70. + (index / 4) as f32 * 170.,
|
|
},
|
|
);
|
|
}
|
|
id
|
|
}
|
|
fn trace(p: &mut Project, oa: Id, sa: Id, kind: TraceKind) {
|
|
let id = Id::new_v4();
|
|
let name = format!("{} ↔ {}", p.named(oa), p.named(sa));
|
|
let alias = p.fresh_alias(&format!("trace_{}", p.named(oa)), "trace", id);
|
|
p.traces.insert(
|
|
id,
|
|
Trace {
|
|
id,
|
|
alias,
|
|
name,
|
|
description: "Reviewed OA/SA correspondence in the coastal rescue example.".into(),
|
|
oa,
|
|
sa,
|
|
kind,
|
|
baseline: Some(TraceBaseline {
|
|
oa: p.properties(oa).unwrap(),
|
|
sa: p.properties(sa).unwrap(),
|
|
semantic: None,
|
|
}),
|
|
},
|
|
);
|
|
}
|
|
|
|
pub fn coastal_rescue() -> Project {
|
|
let mut p = Project::empty();
|
|
p.name = "Coastal rescue — operational need to system behavior".into();
|
|
p.description="A worked OA/SA example. Compare allocation and functional decomposition views; inspect traces, repeated scenario messages, interface contracts, degraded modes, and external engineering artifacts.".into();
|
|
let coordination = add(&mut p, Kind::Entity, Layer::Oa, "Rescue coordination", None);
|
|
let vessel = add(&mut p, Kind::Actor, Layer::Oa, "Vessel in distress", None);
|
|
let role = add(&mut p, Kind::Role, Layer::Oa, "Incident coordinator", None);
|
|
let oa_parent = add(
|
|
&mut p,
|
|
Kind::Activity,
|
|
Layer::Oa,
|
|
"Respond to distress",
|
|
None,
|
|
);
|
|
let report = add(
|
|
&mut p,
|
|
Kind::Activity,
|
|
Layer::Oa,
|
|
"Report distress",
|
|
Some(oa_parent),
|
|
);
|
|
let assess = add(
|
|
&mut p,
|
|
Kind::Activity,
|
|
Layer::Oa,
|
|
"Assess incident",
|
|
Some(oa_parent),
|
|
);
|
|
let oa_cap = add(
|
|
&mut p,
|
|
Kind::Capability,
|
|
Layer::Oa,
|
|
"Protect life at sea",
|
|
None,
|
|
);
|
|
let process = add(
|
|
&mut p,
|
|
Kind::Process,
|
|
Layer::Oa,
|
|
"Distress to response",
|
|
None,
|
|
);
|
|
let oa_item = add(
|
|
&mut p,
|
|
Kind::ExchangeItem,
|
|
Layer::Oa,
|
|
"Distress report",
|
|
None,
|
|
);
|
|
if let Some(SharedBody::ExchangeItem { mechanism, .. }) =
|
|
p.elements.get_mut(&oa_item).unwrap().shared_mut()
|
|
{
|
|
*mechanism = ExchangeMechanism::Event;
|
|
}
|
|
p.relate(RelationKind::Allocation, "Reports distress", vessel, report);
|
|
p.relate(
|
|
RelationKind::Allocation,
|
|
"Assesses incident",
|
|
coordination,
|
|
assess,
|
|
);
|
|
p.relate(
|
|
RelationKind::RoleRealization,
|
|
"Fulfils coordinator role",
|
|
coordination,
|
|
role,
|
|
);
|
|
p.relate(
|
|
RelationKind::RoleAssignment,
|
|
"Coordinates assessment",
|
|
role,
|
|
assess,
|
|
);
|
|
let interaction = p.relate(RelationKind::Interaction, "Distress signal", report, assess);
|
|
if let RelationBody::Interaction { items, .. } =
|
|
&mut p.relations.get_mut(&interaction).unwrap().body
|
|
{
|
|
items.push(oa_item);
|
|
}
|
|
p.relate(
|
|
RelationKind::CapabilityInvolvement,
|
|
"Operational contribution",
|
|
assess,
|
|
oa_cap,
|
|
);
|
|
p.relate(
|
|
RelationKind::ChainInvolvement,
|
|
"Operational realization",
|
|
process,
|
|
oa_cap,
|
|
);
|
|
let oa_occurrence = occurrence(
|
|
&mut p,
|
|
process,
|
|
Layer::Oa,
|
|
"Distress received",
|
|
interaction,
|
|
None,
|
|
None,
|
|
);
|
|
|
|
let system = add(
|
|
&mut p,
|
|
Kind::System,
|
|
Layer::Sa,
|
|
"Rescue coordination system",
|
|
None,
|
|
);
|
|
let actor = add(
|
|
&mut p,
|
|
Kind::SystemActor,
|
|
Layer::Sa,
|
|
"Vessel communication service",
|
|
None,
|
|
);
|
|
let sa_parent = add(
|
|
&mut p,
|
|
Kind::Function,
|
|
Layer::Sa,
|
|
"Manage distress response",
|
|
None,
|
|
);
|
|
let transmit = add(
|
|
&mut p,
|
|
Kind::Function,
|
|
Layer::Sa,
|
|
"Transmit distress report",
|
|
Some(sa_parent),
|
|
);
|
|
let coordinate = add(
|
|
&mut p,
|
|
Kind::Function,
|
|
Layer::Sa,
|
|
"Classify incident and alert operator",
|
|
Some(sa_parent),
|
|
);
|
|
let sa_cap = add(
|
|
&mut p,
|
|
Kind::SystemCapability,
|
|
Layer::Sa,
|
|
"Coordinate rescue response",
|
|
None,
|
|
);
|
|
let chain = add(
|
|
&mut p,
|
|
Kind::FunctionalChain,
|
|
Layer::Sa,
|
|
"Digital distress handling",
|
|
None,
|
|
);
|
|
let mission = add(
|
|
&mut p,
|
|
Kind::Mission,
|
|
Layer::Sa,
|
|
"Support timely rescue decisions",
|
|
None,
|
|
);
|
|
p.relate(
|
|
RelationKind::Allocation,
|
|
"Vessel transmission",
|
|
actor,
|
|
transmit,
|
|
);
|
|
p.relate(
|
|
RelationKind::Allocation,
|
|
"System assessment",
|
|
system,
|
|
coordinate,
|
|
);
|
|
p.relate(
|
|
RelationKind::CapabilityInvolvement,
|
|
"System capability support",
|
|
coordinate,
|
|
sa_cap,
|
|
);
|
|
p.relate(
|
|
RelationKind::ChainInvolvement,
|
|
"Functional chain support",
|
|
chain,
|
|
sa_cap,
|
|
);
|
|
p.relate(
|
|
RelationKind::MissionCapability,
|
|
"Mission capability",
|
|
mission,
|
|
sa_cap,
|
|
);
|
|
let information = add(
|
|
&mut p,
|
|
Kind::ExchangeItem,
|
|
Layer::Sa,
|
|
"Digital distress report",
|
|
None,
|
|
);
|
|
if let Some(SharedBody::ExchangeItem { mechanism, .. }) =
|
|
p.elements.get_mut(&information).unwrap().shared_mut()
|
|
{
|
|
*mechanism = ExchangeMechanism::Event;
|
|
}
|
|
let material = add(
|
|
&mut p,
|
|
Kind::ExchangeItem,
|
|
Layer::Sa,
|
|
"Rescue supply package",
|
|
None,
|
|
);
|
|
*p.elements.get_mut(&material).unwrap().shared_mut().unwrap() = SharedBody::ExchangeItem {
|
|
kind: ExchangeItemKind::Material,
|
|
mechanism: ExchangeMechanism::Flow,
|
|
supertype: None,
|
|
};
|
|
let energy = add(
|
|
&mut p,
|
|
Kind::ExchangeItem,
|
|
Layer::Sa,
|
|
"Backup electrical energy",
|
|
None,
|
|
);
|
|
*p.elements.get_mut(&energy).unwrap().shared_mut().unwrap() = SharedBody::ExchangeItem {
|
|
kind: ExchangeItemKind::Energy,
|
|
mechanism: ExchangeMechanism::Flow,
|
|
supertype: None,
|
|
};
|
|
let field = add(
|
|
&mut p,
|
|
Kind::DataField,
|
|
Layer::Sa,
|
|
"Reported latitude",
|
|
Some(information),
|
|
);
|
|
*p.elements.get_mut(&field).unwrap().shared_mut().unwrap() = SharedBody::DataField {
|
|
type_ref: TypeRef::Real,
|
|
minimum: 1,
|
|
maximum: Some(1),
|
|
unit: "degrees north".into(),
|
|
direction: ParameterDirection::Unspecified,
|
|
storage: FieldStorage::Value,
|
|
default: None,
|
|
};
|
|
let interface = add(
|
|
&mut p,
|
|
Kind::Interface,
|
|
Layer::Sa,
|
|
"Distress reporting interface",
|
|
None,
|
|
);
|
|
p.relate(
|
|
RelationKind::InterfaceItemAllocation,
|
|
"Distress payload",
|
|
interface,
|
|
information,
|
|
);
|
|
let vessel_port = port(
|
|
&mut p,
|
|
actor,
|
|
"Vessel reporting output",
|
|
PortDirection::Out,
|
|
interface,
|
|
);
|
|
let system_port = port(
|
|
&mut p,
|
|
system,
|
|
"System reporting input",
|
|
PortDirection::In,
|
|
interface,
|
|
);
|
|
let function_out = port(
|
|
&mut p,
|
|
transmit,
|
|
"Report function output",
|
|
PortDirection::Out,
|
|
interface,
|
|
);
|
|
let function_in = port(
|
|
&mut p,
|
|
coordinate,
|
|
"Assessment function input",
|
|
PortDirection::In,
|
|
interface,
|
|
);
|
|
let exchange = p.relate(
|
|
RelationKind::FunctionalExchange,
|
|
"Validated distress report",
|
|
transmit,
|
|
coordinate,
|
|
);
|
|
p.relations.get_mut(&exchange).unwrap().body = RelationBody::FunctionalExchange {
|
|
source: transmit,
|
|
target: coordinate,
|
|
source_port: function_out,
|
|
target_port: function_in,
|
|
items: vec![information],
|
|
};
|
|
let boundary = p.relate(
|
|
RelationKind::BoundaryExchange,
|
|
"Distress reporting connection",
|
|
vessel_port,
|
|
system_port,
|
|
);
|
|
if let RelationBody::BoundaryExchange { items, .. } =
|
|
&mut p.relations.get_mut(&boundary).unwrap().body
|
|
{
|
|
items.push(information);
|
|
}
|
|
p.relate(
|
|
RelationKind::PortAllocation,
|
|
"Vessel output represents report output",
|
|
vessel_port,
|
|
function_out,
|
|
);
|
|
p.relate(
|
|
RelationKind::PortAllocation,
|
|
"System input represents assessment input",
|
|
system_port,
|
|
function_in,
|
|
);
|
|
p.relate(
|
|
RelationKind::ExchangeAllocation,
|
|
"Report carried by connection",
|
|
boundary,
|
|
exchange,
|
|
);
|
|
p.relate(
|
|
RelationKind::InterfaceProvision,
|
|
"Reporting service provided",
|
|
vessel_port,
|
|
interface,
|
|
);
|
|
p.relate(
|
|
RelationKind::InterfaceRequirement,
|
|
"Reporting service required",
|
|
system_port,
|
|
interface,
|
|
);
|
|
let sa_occurrence = occurrence(
|
|
&mut p,
|
|
chain,
|
|
Layer::Sa,
|
|
"Report handled",
|
|
exchange,
|
|
None,
|
|
None,
|
|
);
|
|
|
|
let scenario = add(
|
|
&mut p,
|
|
Kind::Scenario,
|
|
Layer::Sa,
|
|
"Repeated distress reports",
|
|
None,
|
|
);
|
|
*p.elements.get_mut(&scenario).unwrap().shared_mut().unwrap() = SharedBody::Scenario {
|
|
viewpoint: ScenarioViewpoint::BoundaryInterface,
|
|
context: Some(sa_cap),
|
|
precondition: "A vessel has detected an emergency and the reporting service is available."
|
|
.into(),
|
|
postcondition: "The operator has a classified incident with the latest vessel report."
|
|
.into(),
|
|
steps: vec![],
|
|
};
|
|
let vessel_line = add(
|
|
&mut p,
|
|
Kind::Lifeline,
|
|
Layer::Sa,
|
|
"Vessel service lifeline",
|
|
Some(scenario),
|
|
);
|
|
*p.elements
|
|
.get_mut(&vessel_line)
|
|
.unwrap()
|
|
.shared_mut()
|
|
.unwrap() = SharedBody::Lifeline {
|
|
represented: Some(actor),
|
|
};
|
|
let system_line = add(
|
|
&mut p,
|
|
Kind::Lifeline,
|
|
Layer::Sa,
|
|
"Coordination system lifeline",
|
|
Some(scenario),
|
|
);
|
|
*p.elements
|
|
.get_mut(&system_line)
|
|
.unwrap()
|
|
.shared_mut()
|
|
.unwrap() = SharedBody::Lifeline {
|
|
represented: Some(system),
|
|
};
|
|
occurrence(
|
|
&mut p,
|
|
scenario,
|
|
Layer::Sa,
|
|
"Initial distress report",
|
|
exchange,
|
|
Some(vessel_line),
|
|
Some(system_line),
|
|
);
|
|
let update = occurrence(
|
|
&mut p,
|
|
scenario,
|
|
Layer::Sa,
|
|
"Updated distress report",
|
|
exchange,
|
|
Some(vessel_line),
|
|
Some(system_line),
|
|
);
|
|
if let Some(SharedBody::Occurrence {
|
|
precondition,
|
|
postcondition,
|
|
..
|
|
}) = p.elements.get_mut(&update).unwrap().shared_mut()
|
|
{
|
|
*precondition = "The vessel has more recent position information.".into();
|
|
*postcondition =
|
|
"The incident position is refreshed without creating a second incident.".into();
|
|
}
|
|
|
|
let machine = add(
|
|
&mut p,
|
|
Kind::StateMachine,
|
|
Layer::Sa,
|
|
"Reporting operation modes",
|
|
Some(system),
|
|
);
|
|
let region = add(
|
|
&mut p,
|
|
Kind::Region,
|
|
Layer::Sa,
|
|
"Reporting quality region",
|
|
Some(machine),
|
|
);
|
|
let initial = add(
|
|
&mut p,
|
|
Kind::Initial,
|
|
Layer::Sa,
|
|
"Start reporting",
|
|
Some(region),
|
|
);
|
|
let normal = add(
|
|
&mut p,
|
|
Kind::Mode,
|
|
Layer::Sa,
|
|
"Normal reporting",
|
|
Some(region),
|
|
);
|
|
let degraded = add(
|
|
&mut p,
|
|
Kind::Mode,
|
|
Layer::Sa,
|
|
"Degraded reporting",
|
|
Some(region),
|
|
);
|
|
p.relate(
|
|
RelationKind::StateTransition,
|
|
"Initialize reporting",
|
|
initial,
|
|
normal,
|
|
);
|
|
let degrade = p.relate(
|
|
RelationKind::StateTransition,
|
|
"Signal degraded",
|
|
normal,
|
|
degraded,
|
|
);
|
|
let timeout = add(&mut p, Kind::Event, Layer::Sa, "Report timeout", None);
|
|
*p.elements.get_mut(&timeout).unwrap().shared_mut().unwrap() = SharedBody::Event {
|
|
body: EventBody::Time {
|
|
kind: TimeEventKind::After,
|
|
expression: "30 s".into(),
|
|
},
|
|
};
|
|
p.relations.get_mut(°rade).unwrap().body = RelationBody::StateTransition {
|
|
source: normal,
|
|
target: degraded,
|
|
transition_kind: TransitionKind::External,
|
|
triggers: vec![timeout],
|
|
effects: vec![],
|
|
trigger: "report_timeout".into(),
|
|
guard: "seconds_since_last_report > 30".into(),
|
|
effect: "Flag the incident and request an operator review.".into(),
|
|
};
|
|
let restore = p.relate(
|
|
RelationKind::StateTransition,
|
|
"Signal restored",
|
|
degraded,
|
|
normal,
|
|
);
|
|
let report_received = add(
|
|
&mut p,
|
|
Kind::Event,
|
|
Layer::Sa,
|
|
"Validated report received",
|
|
None,
|
|
);
|
|
*p.elements
|
|
.get_mut(&report_received)
|
|
.unwrap()
|
|
.shared_mut()
|
|
.unwrap() = SharedBody::Event {
|
|
body: EventBody::Signal {
|
|
items: vec![information],
|
|
},
|
|
};
|
|
p.relations.get_mut(&restore).unwrap().body = RelationBody::StateTransition {
|
|
source: degraded,
|
|
target: normal,
|
|
transition_kind: TransitionKind::External,
|
|
triggers: vec![report_received],
|
|
effects: vec![],
|
|
trigger: "validated_report_received".into(),
|
|
guard: "position_is_current".into(),
|
|
effect: "Clear the degraded-reporting alert.".into(),
|
|
};
|
|
p.relate(
|
|
RelationKind::Availability,
|
|
"Assessment in normal mode",
|
|
coordinate,
|
|
normal,
|
|
);
|
|
p.relate(
|
|
RelationKind::Availability,
|
|
"Assessment in degraded mode",
|
|
coordinate,
|
|
degraded,
|
|
);
|
|
let action = p.relate(
|
|
RelationKind::StateAction,
|
|
"Review on degraded entry",
|
|
degraded,
|
|
coordinate,
|
|
);
|
|
p.relations.get_mut(&action).unwrap().body = RelationBody::StateAction {
|
|
source: degraded,
|
|
target: coordinate,
|
|
phase: StateActionKind::Entry,
|
|
};
|
|
let constraint = add(
|
|
&mut p,
|
|
Kind::Constraint,
|
|
Layer::Sa,
|
|
"Response time budget",
|
|
None,
|
|
);
|
|
*p.elements
|
|
.get_mut(&constraint)
|
|
.unwrap()
|
|
.shared_mut()
|
|
.unwrap() = SharedBody::Constraint {
|
|
expression: "incident_alert_latency <= 120 s".into(),
|
|
constrained: vec![coordinate, exchange],
|
|
};
|
|
for (owner, name, uri, revision, relation) in [
|
|
(
|
|
coordinate,
|
|
"Response implementation",
|
|
"git+https://example.org/rescue/control?path=src/response.rs",
|
|
"design-v2",
|
|
ArtifactRelation::Implements,
|
|
),
|
|
(
|
|
system,
|
|
"Console enclosure CAD",
|
|
"cad://rescue-console/enclosure.step",
|
|
"B.3",
|
|
ArtifactRelation::References,
|
|
),
|
|
] {
|
|
let id = Id::new_v4();
|
|
let alias = p.fresh_alias(name, "artifact", id);
|
|
p.artifact_links.insert(id,ArtifactLink{id,alias,name:name.into(),description:"Illustrative external engineering reference; opening a model does not fetch it.".into(),owner,relation,uri:uri.into(),revision:Some(revision.into()),fragment:None});
|
|
}
|
|
for (oa, sa, kind) in [
|
|
(coordination, system, TraceKind::Participant),
|
|
(vessel, actor, TraceKind::Participant),
|
|
(oa_parent, sa_parent, TraceKind::Refinement),
|
|
(report, transmit, TraceKind::Refinement),
|
|
(assess, coordinate, TraceKind::Refinement),
|
|
(oa_cap, sa_cap, TraceKind::Capability),
|
|
(process, chain, TraceKind::Sequence),
|
|
(oa_occurrence, sa_occurrence, TraceKind::Scenario),
|
|
(interaction, exchange, TraceKind::Exchange),
|
|
(oa_item, information, TraceKind::Item),
|
|
] {
|
|
trace(&mut p, oa, sa, kind);
|
|
}
|
|
let oa_view = diagram(
|
|
&mut p,
|
|
Layer::Oa,
|
|
ProjectionKind::Allocation,
|
|
"OA participants and activities",
|
|
&[coordination, vessel, report, assess],
|
|
);
|
|
let sa_view = diagram(
|
|
&mut p,
|
|
Layer::Sa,
|
|
ProjectionKind::Allocation,
|
|
"SA system boundary and functions",
|
|
&[system, actor, transmit, coordinate],
|
|
);
|
|
let functions = diagram(
|
|
&mut p,
|
|
Layer::Sa,
|
|
ProjectionKind::FunctionalDataflow,
|
|
"SA functional decomposition",
|
|
&[sa_parent, transmit, coordinate],
|
|
);
|
|
let oa_capabilities = diagram(
|
|
&mut p,
|
|
Layer::Oa,
|
|
ProjectionKind::Capabilities,
|
|
"OA capabilities and participants",
|
|
&[coordination, vessel, role, oa_cap],
|
|
);
|
|
let sa_capabilities = diagram(
|
|
&mut p,
|
|
Layer::Sa,
|
|
ProjectionKind::Capabilities,
|
|
"SA missions and capabilities",
|
|
&[system, actor, mission, sa_cap],
|
|
);
|
|
let activities = diagram(
|
|
&mut p,
|
|
Layer::Oa,
|
|
ProjectionKind::FunctionalDataflow,
|
|
"OA activity dataflow",
|
|
&[oa_parent, report, assess],
|
|
);
|
|
execute_batch(
|
|
&p,
|
|
&[
|
|
Command::Layout(oa_view),
|
|
Command::Layout(sa_view),
|
|
Command::Layout(functions),
|
|
Command::Layout(oa_capabilities),
|
|
Command::Layout(sa_capabilities),
|
|
Command::Layout(activities),
|
|
],
|
|
)
|
|
.expect("The bundled OA/SA example is structurally valid")
|
|
}
|