Checkpoint source 7 workflows and in-progress diagram authoring redesign
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.
This commit is contained in:
Codex
2026-09-10 10:06:55 -07:00
parent 4b6b5fc197
commit e2ecfea69b
162 changed files with 17595 additions and 926 deletions
@@ -0,0 +1,529 @@
use super::*;
#[cfg(test)]
#[path = "analysis_tests.rs"]
mod tests;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ReferenceBoundary {
Entry,
Exit,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ContextVertex {
pub address: ContextAddress,
pub boundary: Option<ReferenceBoundary>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContextEdgeKind {
Authored,
SyntheticBoundary,
LegacyOrder,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContextEdge {
pub relation: Option<Id>,
pub instance: Vec<Id>,
pub source: ContextVertex,
pub target: ContextVertex,
pub guard: String,
pub kind: ContextEdgeKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContextAssembly {
pub relation: Id,
pub instance: Vec<Id>,
pub source: ContextAddress,
pub target: ContextAddress,
pub purpose: ContextualLinkPurpose,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContextNotice {
pub address: ContextAddress,
pub code: &'static str,
pub message: String,
pub relations: Vec<Id>,
}
#[derive(Debug, Clone, Copy)]
pub struct AnalysisLimits {
pub nodes: usize,
pub edges: usize,
}
impl Default for AnalysisLimits {
fn default() -> Self {
Self {
nodes: MAX_ANALYSIS_NODES,
edges: MAX_ANALYSIS_EDGES,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ContextAnalysis {
pub nodes: BTreeMap<ContextAddress, ResolvedOccurrence>,
pub precedence: Vec<ContextEdge>,
pub assembly: Vec<ContextAssembly>,
pub entries: Vec<ContextVertex>,
pub exits: Vec<ContextVertex>,
pub notices: Vec<ContextNotice>,
/// A partial expansion must never be used for complete reachability conclusions.
pub complete: bool,
}
struct Builder<'a, 'p> {
index: &'a TopologyIndex<'p>,
root: Id,
limits: AnalysisLimits,
result: ContextAnalysis,
definitions: BTreeMap<Id, Vec<&'p Relation>>,
examined_edges: usize,
exhausted: bool,
}
impl TopologyIndex<'_> {
pub fn analyze(&self, owner: Id, limits: AnalysisLimits) -> ContextAnalysis {
self.analyze_counted(owner, limits).0
}
fn analyze_counted(&self, owner: Id, limits: AnalysisLimits) -> (ContextAnalysis, usize) {
let mut definitions: BTreeMap<_, Vec<_>> = BTreeMap::new();
for (owner, relations) in &self.link_definitions {
definitions.insert(
*owner,
relations
.iter()
.filter_map(|id| self.project.relations.get(id))
.collect(),
);
}
let mut b = Builder {
index: self,
root: owner,
limits,
result: ContextAnalysis {
complete: true,
..ContextAnalysis::default()
},
definitions,
examined_edges: 0,
exhausted: false,
};
(b.result.entries, b.result.exits) = b.expand(owner, &[], &mut BTreeSet::new());
if b.result.complete {
b.cardinality();
b.connectivity();
}
(b.result, b.examined_edges)
}
pub fn has_contextual_links(&self, owner: Id) -> bool {
self.contextual_callers.contains(&owner)
}
}
impl Builder<'_, '_> {
fn address(&self, path: &[Id], occurrence: Id) -> ContextAddress {
ContextAddress {
owner: self.root,
endpoint: OccurrenceEndpoint {
references: path.to_vec(),
occurrence,
},
}
}
fn vertex(&self, address: ContextAddress, source: bool) -> ContextVertex {
let reference = self
.index
.project
.elements
.get(&address.endpoint.occurrence)
.and_then(Element::shared)
.is_some_and(|s| {
matches!(
s,
SharedBody::Occurrence {
body: OccurrenceBody::SequenceReference { .. },
..
}
)
});
ContextVertex {
address,
boundary: reference.then_some(if source {
ReferenceBoundary::Exit
} else {
ReferenceBoundary::Entry
}),
}
}
fn incomplete(&mut self, address: ContextAddress, code: &'static str, message: &str) {
self.result.complete = false;
if !self
.result
.notices
.iter()
.any(|n| n.address == address && n.code == code)
{
self.result.notices.push(ContextNotice {
address,
code,
message: message.into(),
relations: vec![],
});
}
}
// Reserve work before resolving an authored endpoint, not merely before storing
// its output. Repeated malformed or filtered endpoints consume the same budget.
fn reserve_edge(&mut self, address: ContextAddress) -> bool {
if self.exhausted {
return false;
}
if self.examined_edges >= self.limits.edges {
self.exhausted = true;
self.incomplete(
address,
"context_analysis_limit",
"Contextual edge limit reached; connectivity analysis is incomplete.",
);
return false;
}
self.examined_edges += 1;
true
}
fn edge(&mut self, edge: ContextEdge) -> bool {
if !self.reserve_edge(edge.source.address.clone()) {
return false;
}
self.result.precedence.push(edge);
true
}
fn expand(
&mut self,
sequence: Id,
prefix: &[Id],
active: &mut BTreeSet<Id>,
) -> (Vec<ContextVertex>, Vec<ContextVertex>) {
if self.exhausted {
return (vec![], vec![]);
}
if prefix.len() > MAX_REFERENCE_DEPTH || !active.insert(sequence) {
self.incomplete(
self.address(prefix, sequence),
"context_analysis_incomplete",
"Recursive or over-depth reuse has no proven boundary path.",
);
return (vec![], vec![]);
}
let children = self.index.contributions(sequence);
if children.is_empty() {
self.incomplete(
self.address(prefix, sequence),
"context_analysis_incomplete",
"An empty or unresolved sequence has no proven boundary path.",
);
active.remove(&sequence);
return (vec![], vec![]);
}
let start = self.result.precedence.len();
for id in &children {
let address = self.address(prefix, *id);
if self.result.nodes.len() >= self.limits.nodes {
self.exhausted = true;
self.incomplete(
address,
"context_analysis_limit",
"Contextual node limit reached; connectivity analysis is incomplete.",
);
break;
}
match self.index.resolve(self.root, &address.endpoint) {
Ok(resolved) => {
self.result.nodes.insert(address.clone(), resolved);
}
Err(e) => {
self.incomplete(address, "context_analysis_incomplete", &e.message);
continue;
}
}
let reference = self.index.project.elements[id]
.shared()
.and_then(|s| match s {
SharedBody::Occurrence {
body: OccurrenceBody::SequenceReference { sequence },
..
} => Some(*sequence),
_ => None,
});
if let Some(reference) = reference {
let Some(callee) = reference else {
self.incomplete(
address,
"context_analysis_incomplete",
"An unresolved reference has no proven boundary path.",
);
continue;
};
let mut path = prefix.to_vec();
path.push(*id);
let (entries, exits) = self.expand(callee, &path, active);
if self.exhausted {
active.remove(&sequence);
return (vec![], vec![]);
}
if entries.is_empty() || exits.is_empty() {
self.incomplete(
address.clone(),
"context_analysis_incomplete",
"No referenced entry or exit is proven; no bypass is inferred.",
);
}
for target in entries {
if !self.edge(ContextEdge {
relation: None,
instance: prefix.to_vec(),
source: self.vertex(address.clone(), false),
target,
guard: String::new(),
kind: ContextEdgeKind::SyntheticBoundary,
}) {
break;
}
}
for source in exits {
if !self.edge(ContextEdge {
relation: None,
instance: prefix.to_vec(),
source,
target: self.vertex(address.clone(), true),
guard: String::new(),
kind: ContextEdgeKind::SyntheticBoundary,
}) {
break;
}
}
}
if self.exhausted {
break;
}
}
if self.exhausted {
active.remove(&sequence);
return (vec![], vec![]);
}
let relations = self.definitions.get(&sequence).cloned().unwrap_or_default();
for r in &relations {
if !self.reserve_edge(self.address(prefix, r.source())) {
break;
}
let (source, target, purpose) = match &r.body {
RelationBody::SequenceLink {
source,
target,
guard,
} => (
OccurrenceEndpoint {
references: vec![],
occurrence: *source,
},
OccurrenceEndpoint {
references: vec![],
occurrence: *target,
},
ContextualLinkPurpose::Precedence {
guard: guard.clone(),
},
),
RelationBody::ContextualLink {
source,
target,
purpose,
..
} => (source.clone(), target.clone(), purpose.clone()),
_ => continue,
};
let qualify = |mut endpoint: OccurrenceEndpoint| {
let mut path = prefix.to_vec();
path.extend(endpoint.references);
endpoint.references = path;
ContextAddress {
owner: self.root,
endpoint,
}
};
let source = qualify(source);
let target = qualify(target);
if !self.result.nodes.contains_key(&source) || !self.result.nodes.contains_key(&target)
{
self.incomplete(
source,
"context_analysis_incomplete",
"A link endpoint is unresolved in this bounded analysis.",
);
continue;
}
match purpose {
ContextualLinkPurpose::Precedence { guard } => {
self.result.precedence.push(ContextEdge {
relation: Some(r.id),
instance: prefix.to_vec(),
source: self.vertex(source, true),
target: self.vertex(target, false),
guard,
kind: ContextEdgeKind::Authored,
})
}
purpose => {
self.result.assembly.push(ContextAssembly {
relation: r.id,
instance: prefix.to_vec(),
source,
target,
purpose,
});
}
}
}
if self.exhausted {
active.remove(&sequence);
return (vec![], vec![]);
}
if relations.is_empty()
&& children.iter().all(|id| {
matches!(
self.index.project.elements[id].shared(),
Some(SharedBody::Occurrence {
body: OccurrenceBody::Exchange { .. },
..
})
)
})
{
for pair in children.windows(2) {
if !self.edge(ContextEdge {
relation: None,
instance: prefix.to_vec(),
source: self.vertex(self.address(prefix, pair[0]), true),
target: self.vertex(self.address(prefix, pair[1]), false),
guard: String::new(),
kind: ContextEdgeKind::LegacyOrder,
}) {
break;
}
}
}
if self.exhausted {
active.remove(&sequence);
return (vec![], vec![]);
}
// Intrinsic boundaries are determined before any enclosing caller links.
let edges = &self.result.precedence[start..];
let targets: BTreeSet<_> = edges.iter().map(|e| &e.target).collect();
let sources: BTreeSet<_> = edges.iter().map(|e| &e.source).collect();
let entries = children
.iter()
.map(|id| self.vertex(self.address(prefix, *id), false))
.filter(|v| !targets.contains(v))
.collect();
let exits = children
.iter()
.map(|id| self.vertex(self.address(prefix, *id), true))
.filter(|v| !sources.contains(v))
.collect();
active.remove(&sequence);
(entries, exits)
}
fn cardinality(&mut self) {
// Index authored incidence once; synthetic boundaries never count as controls.
let mut incoming: BTreeMap<_, Vec<_>> = BTreeMap::new();
let mut outgoing: BTreeMap<_, Vec<_>> = BTreeMap::new();
for edge in &self.result.precedence {
if edge.kind == ContextEdgeKind::Authored {
incoming.entry(&edge.target.address).or_default().push(edge);
outgoing.entry(&edge.source.address).or_default().push(edge);
}
}
for address in self.result.nodes.keys() {
let ins = incoming.get(address).cloned().unwrap_or_default();
let outs = outgoing.get(address).cloned().unwrap_or_default();
let before = ins.len();
let after = outs.len();
let control = match self.index.project.elements[&address.endpoint.occurrence].shared() {
Some(SharedBody::Occurrence {
body: OccurrenceBody::Control { kind },
..
}) => Some(*kind),
_ => None,
};
let issue = match control {
Some(kind) => { let valid = match kind { ControlKind::Choice | ControlKind::Fork => before == 1 && after >= 2, ControlKind::Merge | ControlKind::Join => before >= 2 && after == 1, ControlKind::Loop => before >= 1 && after >= 2 }; (!valid).then_some(("control_cardinality", format!("{kind:?} has {before} incoming and {after} outgoing authored precedence links in this caller context. Review the intended paths."))) }
None => (before > 1 || after > 1).then_some(("ambiguous_sequence_branch", "This contribution has multiple incoming or outgoing precedence links in this caller context. Review whether explicit merge/join or branching control is needed to describe the intended paths.".into())),
};
if let Some((code, message)) = issue {
self.result.notices.push(ContextNotice {
address: address.clone(),
code,
message,
relations: ins.iter().chain(&outs).filter_map(|e| e.relation).collect(),
});
}
if matches!(control, Some(ControlKind::Choice | ControlKind::Loop)) {
for edge in outs.iter().filter(|e| e.guard.trim().is_empty()) {
self.result.notices.push(ContextNotice { address: address.clone(), code: "missing_sequence_guard", message: "Describe the choice/loop condition for this path, or use an explicit 'else' guard.".into(), relations: edge.relation.into_iter().collect() });
}
}
}
}
fn connectivity(&mut self) {
let mut forward: BTreeMap<_, Vec<_>> = BTreeMap::new();
let mut reverse: BTreeMap<_, Vec<_>> = BTreeMap::new();
for edge in &self.result.precedence {
forward
.entry(edge.source.clone())
.or_default()
.push(edge.target.clone());
reverse
.entry(edge.target.clone())
.or_default()
.push(edge.source.clone());
}
let visit = |starts: &[ContextVertex],
graph: &BTreeMap<ContextVertex, Vec<ContextVertex>>| {
let mut pending = starts.to_vec();
let mut seen = BTreeSet::new();
while let Some(vertex) = pending.pop() {
if seen.insert(vertex.clone()) {
pending.extend(graph.get(&vertex).into_iter().flatten().cloned());
}
}
seen
};
let from_start = visit(&self.result.entries, &forward);
let to_end = visit(&self.result.exits, &reverse);
for address in self.result.nodes.keys() {
let entry = self.vertex(address.clone(), false);
let exit = self.vertex(address.clone(), true);
for (missing, code, message) in [
(
!from_start.contains(&entry),
"unreachable_contribution",
"No path from a structural caller entry reaches this contribution in this context.",
),
(
!to_end.contains(&exit),
"nonterminating_contribution",
"No structural caller exit is reachable from this contribution in this context; review the intended loop.",
),
(
self.result.nodes.len() > 1
&& !reverse.contains_key(&entry)
&& !forward.contains_key(&exit),
"isolated_contribution",
"This contribution has no incoming or outgoing precedence path in this caller context; assembly incidence is separate.",
),
] {
if missing {
self.result.notices.push(ContextNotice {
address: address.clone(),
code,
message: message.into(),
relations: vec![],
});
}
}
}
}
}
@@ -0,0 +1,172 @@
use super::*;
fn occurrence(p: &mut Project, owner: Id, name: &str, body: OccurrenceBody) -> Id {
let id = p
.add_element(Kind::Occurrence, Layer::Sa, name, Some(owner))
.unwrap();
*p.elements.get_mut(&id).unwrap().shared_mut().unwrap() = SharedBody::Occurrence {
body,
precondition: String::new(),
postcondition: String::new(),
};
p.elements
.get_mut(&owner)
.unwrap()
.steps_mut()
.unwrap()
.push(id);
id
}
fn repeated(references: usize, links: usize) -> (Project, Id, Id) {
let mut p = Project::empty();
let root = p
.add_element(Kind::FunctionalChain, Layer::Sa, "Caller", None)
.unwrap();
let procedure = p
.add_element(Kind::FunctionalChain, Layer::Sa, "Reusable procedure", None)
.unwrap();
let mut leaves = Vec::new();
for name in ["A", "B"] {
let action = p
.add_element(Kind::Function, Layer::Sa, name, None)
.unwrap();
leaves.push(occurrence(
&mut p,
procedure,
name,
OccurrenceBody::Action {
action: Some(action),
lifeline: None,
},
));
}
for _ in 0..links {
p.relate(
RelationKind::SequenceLink,
"Authored A to B",
leaves[0],
leaves[1],
);
}
for _ in 0..references {
occurrence(
&mut p,
root,
"Reuse",
OccurrenceBody::SequenceReference {
sequence: Some(procedure),
},
);
}
(p, root, procedure)
}
#[test]
fn edge_work_budget_stops_repeated_expansion_not_just_output_storage() {
// Only ~3,000 possible contribution nodes, but a million authored edge
// instances. The edge budget must stop actual work before later references.
let (p, root, _) = repeated(1_000, 1_000);
let limits = AnalysisLimits::default();
let index = TopologyIndex::with_cache_capacity(&p, 1);
let (first, attempts) = index.analyze_counted(root, limits);
assert_eq!(attempts, limits.edges);
assert_eq!(first.precedence.len(), limits.edges);
assert!(!first.complete);
assert!(first.entries.is_empty() && first.exits.is_empty());
assert!(
first.nodes.len() < 1_000,
"later caller references must not be expanded"
);
assert_eq!(
first
.notices
.iter()
.filter(|n| n.code == "context_analysis_limit")
.count(),
1
);
assert!(
first
.notices
.iter()
.all(|n| n.code == "context_analysis_limit")
);
let (warm, warm_attempts) = index.analyze_counted(root, limits);
assert_eq!(warm_attempts, attempts);
assert_eq!(warm.nodes, first.nodes);
assert_eq!(warm.precedence, first.precedence);
assert_eq!(warm.notices, first.notices);
drop(warm);
let (uncached, uncached_attempts) =
TopologyIndex::with_cache_capacity(&p, 0).analyze_counted(root, limits);
assert_eq!(uncached_attempts, attempts);
assert_eq!(uncached.precedence, first.precedence);
assert_eq!(uncached.notices, first.notices);
}
#[test]
fn unresolved_authored_edges_consume_work_budget_without_stored_output() {
let (mut p, root, _) = repeated(20, 100);
let missing = Id::nil();
for relation in p.relations.values_mut() {
relation.body.set_endpoints(relation.source(), missing);
}
let (result, attempts) = TopologyIndex::new(&p).analyze_counted(
root,
AnalysisLimits {
nodes: 1_000,
edges: 17,
},
);
assert_eq!(attempts, 17);
assert!(result.precedence.is_empty());
assert_eq!(result.nodes.len(), 3);
assert!(!result.complete);
assert!(result.entries.is_empty() && result.exits.is_empty());
assert_eq!(
result
.notices
.iter()
.filter(|n| n.code == "context_analysis_limit")
.count(),
1
);
}
#[test]
fn exact_edge_budget_includes_reference_boundaries_and_node_abort_has_no_bypass() {
let (p, root, _) = repeated(1, 2);
let index = TopologyIndex::new(&p);
let (complete, count) = index.analyze_counted(root, AnalysisLimits { nodes: 3, edges: 4 });
assert!(complete.complete);
assert_eq!(count, 4); // two authored edges plus entry and exit connectors
assert_eq!(
complete
.precedence
.iter()
.filter(|e| e.kind == ContextEdgeKind::SyntheticBoundary)
.count(),
2
);
for limits in [
AnalysisLimits { nodes: 3, edges: 3 },
AnalysisLimits {
nodes: 1,
edges: 10,
},
] {
let (partial, count) = index.analyze_counted(root, limits);
assert!(!partial.complete);
assert!(partial.entries.is_empty() && partial.exits.is_empty());
assert!(count <= limits.edges);
assert_eq!(
partial
.notices
.iter()
.filter(|n| n.code == "context_analysis_limit")
.count(),
1
);
}
}