Complete source 6 engineering workflows and preserve release validation evidence
This commit is contained in:
@@ -138,119 +138,10 @@ fn work_exchange(kind: RelationKind) -> bool {
|
||||
/// Only ordered, owned occurrences contribute. Each identity is visited once,
|
||||
/// including reused containers; this remains bounded even on malformed drafts.
|
||||
fn included_evidence(p: &Project) -> (BTreeSet<Id>, BTreeSet<Id>) {
|
||||
let mut pending: Vec<_> = p
|
||||
.elements
|
||||
.values()
|
||||
.filter(|e| {
|
||||
matches!(
|
||||
e.kind(),
|
||||
Kind::Process | Kind::FunctionalChain | Kind::Scenario
|
||||
)
|
||||
})
|
||||
.map(|e| e.id)
|
||||
.collect();
|
||||
let mut seen = BTreeSet::new();
|
||||
let mut work = BTreeSet::new();
|
||||
let mut exchanges = BTreeSet::new();
|
||||
while let Some(id) = pending.pop() {
|
||||
if !seen.insert(id) {
|
||||
continue;
|
||||
}
|
||||
let Some(element) = p.elements.get(&id) else {
|
||||
continue;
|
||||
};
|
||||
if let Some(steps) = element.steps() {
|
||||
pending.extend(
|
||||
steps
|
||||
.iter()
|
||||
.filter(|step| {
|
||||
p.elements.get(step).is_some_and(|child| {
|
||||
child.kind() == Kind::Occurrence
|
||||
&& child.parent == Some(id)
|
||||
&& child.layer() == element.layer()
|
||||
})
|
||||
})
|
||||
.copied(),
|
||||
);
|
||||
}
|
||||
let Some(SharedBody::Occurrence { body, .. }) = element.shared() else {
|
||||
continue;
|
||||
};
|
||||
match body {
|
||||
OccurrenceBody::Action {
|
||||
action: Some(action),
|
||||
..
|
||||
} => {
|
||||
if p.elements
|
||||
.get(action)
|
||||
.is_some_and(|e| e.kind().is_work() && e.layer() == element.layer())
|
||||
{
|
||||
work.insert(*action);
|
||||
}
|
||||
}
|
||||
OccurrenceBody::Exchange {
|
||||
exchange: Some(exchange),
|
||||
..
|
||||
} => {
|
||||
if let Some(relation) = p.relations.get(exchange)
|
||||
&& work_exchange(relation.kind())
|
||||
&& [relation.source(), relation.target()].iter().all(|id| {
|
||||
p.elements
|
||||
.get(id)
|
||||
.is_some_and(|e| e.kind().is_work() && e.layer() == element.layer())
|
||||
})
|
||||
{
|
||||
exchanges.insert(*exchange);
|
||||
work.extend([relation.source(), relation.target()]);
|
||||
}
|
||||
}
|
||||
OccurrenceBody::Fragment { branches, .. } => {
|
||||
pending.extend(
|
||||
branches
|
||||
.iter()
|
||||
.filter(|branch| {
|
||||
p.elements.get(branch).is_some_and(|child| {
|
||||
child.parent == Some(id)
|
||||
&& child.layer() == element.layer()
|
||||
&& matches!(
|
||||
child.shared(),
|
||||
Some(SharedBody::Occurrence {
|
||||
body: OccurrenceBody::Branch { .. },
|
||||
..
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
.copied(),
|
||||
);
|
||||
}
|
||||
OccurrenceBody::SequenceReference {
|
||||
sequence: Some(sequence),
|
||||
} => {
|
||||
if let Some(owner) = element.parent.and_then(|id| p.elements.get(&id))
|
||||
&& matches!(owner.kind(), Kind::Process | Kind::FunctionalChain)
|
||||
&& p.elements.get(sequence).is_some_and(|target| {
|
||||
target.kind() == owner.kind() && target.layer() == element.layer()
|
||||
})
|
||||
{
|
||||
pending.push(*sequence);
|
||||
}
|
||||
}
|
||||
OccurrenceBody::ScenarioUse {
|
||||
scenario: Some(scenario),
|
||||
..
|
||||
} if p.elements.get(scenario).is_some_and(|target| {
|
||||
target.kind() == Kind::Scenario && target.layer() == element.layer()
|
||||
}) =>
|
||||
{
|
||||
pending.push(*scenario);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let crate::view_options::BehaviorEvidence { work, exchanges } =
|
||||
crate::view_options::all_behavior_evidence(p);
|
||||
(work, exchanges)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user