Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c2b06b63f |
@@ -1,881 +0,0 @@
|
||||
//! Experimental geometry evidence, not a native selection or usability oracle.
|
||||
//! See harness/experiments/diagram-readability-20260929/README.md.
|
||||
use oa_core::{Diagram, Id, Position, Project, persistence, projection, routing, validation};
|
||||
use serde_json::{Value, json};
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::{self, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
const MIXED: &[u8] = include_bytes!(
|
||||
"../../../harness/experiments/diagram-readability-20260929/mixed-dispatch-original.json"
|
||||
);
|
||||
const WARNINGS: &[u8] = include_bytes!(
|
||||
"../../../harness/experiments/diagram-readability-20260929/mixed-dispatch-expected-diagnostics.json"
|
||||
);
|
||||
const RELEASE: &[u8] = include_bytes!("../../../examples/release1/model.json");
|
||||
const RELEASE_WARNINGS: &[u8] =
|
||||
include_bytes!("../../../examples/release1/expected-diagnostics.json");
|
||||
const EIGHT_VIEW: &[u8] = include_bytes!(
|
||||
"../../../harness/experiments/diagram-readability-20260929/eight-card-view.json"
|
||||
);
|
||||
const MAIN: &str = "00000000-0000-0000-0000-0000000186a1";
|
||||
const EIGHT: &str = "00000000-0038-4000-8000-000000000001";
|
||||
|
||||
fn canonical_diagnostics(value: Value) -> Result<Vec<String>> {
|
||||
let mut rows = value
|
||||
.as_array()
|
||||
.ok_or("Expected a diagnostics array")?
|
||||
.iter()
|
||||
.map(serde_json::to_string)
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
rows.sort();
|
||||
Ok(rows)
|
||||
}
|
||||
|
||||
fn admit(bytes: &[u8], baseline: &[u8]) -> Result<Project> {
|
||||
let project = persistence::decode(bytes)?;
|
||||
let issues = validation::validate(&project);
|
||||
if issues
|
||||
.iter()
|
||||
.any(|i| i.severity == validation::Severity::Error)
|
||||
{
|
||||
return Err(format!("Invalid project: {}", serde_json::to_string(&issues)?).into());
|
||||
}
|
||||
if canonical_diagnostics(serde_json::to_value(&issues)?)?
|
||||
!= canonical_diagnostics(serde_json::from_slice(baseline)?)?
|
||||
{
|
||||
return Err(format!(
|
||||
"Unexpected diagnostics; review without automatically accepting: {}",
|
||||
serde_json::to_string(&issues)?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
Ok(project)
|
||||
}
|
||||
|
||||
fn representative() -> Result<Project> {
|
||||
let mut project = admit(RELEASE, RELEASE_WARNINGS)?;
|
||||
let view: Diagram = serde_json::from_slice(EIGHT_VIEW)?;
|
||||
if project.diagrams.insert(view.id, view).is_some() {
|
||||
return Err("Representative view ID collision".into());
|
||||
}
|
||||
admit(&serde_json::to_vec(&project)?, RELEASE_WARNINGS)
|
||||
}
|
||||
|
||||
fn rect(point: Position, origin: Position, size: oa_core::Size) -> bool {
|
||||
point.x >= origin.x
|
||||
&& point.x <= origin.x + size.width
|
||||
&& point.y >= origin.y
|
||||
&& point.y <= origin.y + size.height
|
||||
}
|
||||
|
||||
fn distance(point: Position, a: Position, b: Position) -> f32 {
|
||||
let dx = b.x - a.x;
|
||||
let dy = b.y - a.y;
|
||||
let length = dx * dx + dy * dy;
|
||||
let t = if length == 0. {
|
||||
0.
|
||||
} else {
|
||||
(((point.x - a.x) * dx + (point.y - a.y) * dy) / length).clamp(0., 1.)
|
||||
};
|
||||
(point.x - a.x - t * dx).hypot(point.y - a.y - t * dy)
|
||||
}
|
||||
|
||||
// Intentionally returns every distinct candidate, with no selected-edge bias,
|
||||
// UUID winner, click dispatch, viewport clipping, or gesture simulation.
|
||||
fn candidates(
|
||||
project: &Project,
|
||||
view: &projection::ProjectedView,
|
||||
routed: &routing::RoutedView,
|
||||
point: Position,
|
||||
zoom: f32,
|
||||
) -> Value {
|
||||
let edges: Vec<_> = routed
|
||||
.edges
|
||||
.values()
|
||||
.filter_map(|edge| {
|
||||
let segments: Vec<_> = edge
|
||||
.points
|
||||
.windows(2)
|
||||
.enumerate()
|
||||
.filter_map(|(i, pair)| {
|
||||
let d = distance(point, pair[0], pair[1]);
|
||||
(d <= 7. / zoom).then(|| json!({"index":i,"distance":d}))
|
||||
})
|
||||
.collect();
|
||||
(!segments.is_empty()).then(|| json!({"edge":edge.id,"segments":segments}))
|
||||
})
|
||||
.collect();
|
||||
let nodes: Vec<_> = view
|
||||
.nodes
|
||||
.iter()
|
||||
.filter(|n| rect(point, n.position, n.size))
|
||||
.map(|n| n.id)
|
||||
.collect();
|
||||
let labels: Vec<_> = routed
|
||||
.edges
|
||||
.values()
|
||||
.filter(|e| {
|
||||
!e.label.text.is_empty() && rect(point, e.label.bounds.position, e.label.bounds.size)
|
||||
})
|
||||
.map(|e| e.id)
|
||||
.collect();
|
||||
let association_labels: Vec<_> = routed
|
||||
.edges
|
||||
.values()
|
||||
.flat_map(|e| {
|
||||
project
|
||||
.relations
|
||||
.get(&e.id)
|
||||
.into_iter()
|
||||
.flat_map(move |relation| {
|
||||
routing::association_end_geometry(relation, e)
|
||||
.into_iter()
|
||||
.filter(move |end| {
|
||||
rect(point, end.label.bounds.position, end.label.bounds.size)
|
||||
})
|
||||
.map(move |end| json!({"edge":e.id,"source_end":end.source_end}))
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let radius = (10. / zoom).max(10.);
|
||||
let ports: Vec<_> = view
|
||||
.ports
|
||||
.iter()
|
||||
.filter(|p| {
|
||||
(p.position.x - point.x).abs() <= radius && (p.position.y - point.y).abs() <= radius
|
||||
})
|
||||
.map(|p| json!({"element":p.element,"owner":p.owner}))
|
||||
.collect();
|
||||
json!({"world_point":point,"zoom":zoom,"edge_candidates":edges,
|
||||
"node_occluders":nodes,"label_occluders":labels,"association_label_occluders":association_labels,"port_occluders":ports})
|
||||
}
|
||||
|
||||
fn unobscured(value: &Value) -> bool {
|
||||
[
|
||||
"node_occluders",
|
||||
"label_occluders",
|
||||
"association_label_occluders",
|
||||
"port_occluders",
|
||||
]
|
||||
.iter()
|
||||
.all(|key| value[key].as_array().is_some_and(Vec::is_empty))
|
||||
}
|
||||
|
||||
fn snapshot(project: &Project, diagram: Id, point: Position, zoom: f32) -> Result<Value> {
|
||||
if !zoom.is_finite() || zoom <= 0. || !point.x.is_finite() || !point.y.is_finite() {
|
||||
return Err("Point must be finite; zoom must be finite and positive".into());
|
||||
}
|
||||
let original = project.clone();
|
||||
let diagram = project.diagrams.get(&diagram).ok_or("Unknown diagram")?;
|
||||
let view = projection::project_view(project, diagram.id);
|
||||
let routed = routing::route_diagram(project, diagram, &view);
|
||||
let mut inventory = Vec::new();
|
||||
for edge in &view.edges {
|
||||
let (kind, source, target) = if let Some(r) = project.relations.get(&edge.id) {
|
||||
(format!("{:?}", r.kind()), r.source(), r.target())
|
||||
} else if let Some(t) = project.traces.get(&edge.id) {
|
||||
(format!("Trace:{:?}", t.kind), t.oa, t.sa)
|
||||
} else {
|
||||
return Err("Projected edge has no semantic identity".into());
|
||||
};
|
||||
inventory.push(
|
||||
json!({"id":edge.id,"kind":kind,"source":source,"target":target,
|
||||
"source_port":edge.source_port,"target_port":edge.target_port,
|
||||
"projected_source":edge.source,"projected_target":edge.target,"trace":edge.trace}),
|
||||
);
|
||||
}
|
||||
inventory.sort_by_key(|row| row["id"].to_string());
|
||||
let expected: Option<Value> = if diagram.id.to_string() == MAIN {
|
||||
Some(serde_json::from_slice(include_bytes!(
|
||||
"../../../harness/experiments/diagram-readability-20260929/mixed-answer-key.json"
|
||||
))?)
|
||||
} else if diagram.id.to_string() == EIGHT {
|
||||
Some(serde_json::from_slice(include_bytes!(
|
||||
"../../../harness/experiments/diagram-readability-20260929/eight-answer-key.json"
|
||||
))?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if expected
|
||||
.as_ref()
|
||||
.is_some_and(|key| *key != json!(inventory))
|
||||
{
|
||||
return Err(format!(
|
||||
"Projected semantic inventory differs from independently declared answer key: {}",
|
||||
json!(inventory)
|
||||
)
|
||||
.into());
|
||||
}
|
||||
let mut edges = Vec::new();
|
||||
let mut alternate = Vec::new();
|
||||
for edge in routed.edges.values() {
|
||||
let projected = view
|
||||
.edges
|
||||
.iter()
|
||||
.find(|p| p.id == edge.id)
|
||||
.ok_or("Routed edge missing projected identity")?;
|
||||
let semantic = if let Some(relation) = project.relations.get(&edge.id) {
|
||||
json!({"relation":relation,"source_element":project.elements.get(&relation.source()),
|
||||
"target_element":project.elements.get(&relation.target())})
|
||||
} else {
|
||||
json!({"trace":project.traces.get(&edge.id)})
|
||||
};
|
||||
edges.push(
|
||||
json!({"id":edge.id,"projected":projected,"semantic":semantic,
|
||||
"points":edge.points,"label":{"text":edge.label.text,"fraction":edge.label.fraction,
|
||||
"anchor":edge.label.anchor,"center":edge.label.center,
|
||||
"position":edge.label.bounds.position,"size":edge.label.bounds.size},
|
||||
"effective_pins":edge.pins,"pin_fractions":edge.pin_fractions,
|
||||
"authored_route":diagram.routes.iter().find(|r| r.edge == edge.id),
|
||||
"custom_suspended":edge.custom_suspended,
|
||||
"route_warnings":edge.warnings.iter().map(|w| format!("{w:?}")).collect::<Vec<_>>()}),
|
||||
);
|
||||
// A positive sample proves a geometric alternate under this query policy.
|
||||
// Failure to find one does NOT prove global inaccessibility.
|
||||
let mut line_witness = None;
|
||||
for pair in edge.points.windows(2) {
|
||||
for t in [0.25, 0.5, 0.75] {
|
||||
let p = Position {
|
||||
x: pair[0].x + (pair[1].x - pair[0].x) * t,
|
||||
y: pair[0].y + (pair[1].y - pair[0].y) * t,
|
||||
};
|
||||
let hits = candidates(project, &view, &routed, p, zoom);
|
||||
if unobscured(&hits)
|
||||
&& hits["edge_candidates"]
|
||||
.as_array()
|
||||
.is_some_and(|a| a.len() == 1)
|
||||
{
|
||||
line_witness = Some(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if line_witness.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let label_hits = candidates(project, &view, &routed, edge.label.center, zoom);
|
||||
let label_witness = !edge.label.text.is_empty()
|
||||
&& label_hits["node_occluders"]
|
||||
.as_array()
|
||||
.is_some_and(Vec::is_empty)
|
||||
&& label_hits["port_occluders"]
|
||||
.as_array()
|
||||
.is_some_and(Vec::is_empty)
|
||||
&& label_hits["association_label_occluders"]
|
||||
.as_array()
|
||||
.is_some_and(Vec::is_empty)
|
||||
&& label_hits["label_occluders"]
|
||||
.as_array()
|
||||
.is_some_and(|a| a.len() == 1);
|
||||
alternate.push(json!({"edge":edge.id,"unoccluded_unique_segment_sample":line_witness,
|
||||
"unoccluded_unique_label_center":label_witness.then_some(edge.label.center),
|
||||
"negative_result":"No sampled witness is not proof of global inaccessibility",
|
||||
"native_access":"Not evaluated; Inspector, viewport, selected handles and gesture state excluded"}));
|
||||
}
|
||||
if *project != original {
|
||||
return Err("Projection/routing changed the Project".into());
|
||||
}
|
||||
let query = candidates(project, &view, &routed, point, zoom);
|
||||
let historical_point = Position { x: 1982., y: 375. };
|
||||
let historical_query = candidates(project, &view, &routed, historical_point, 1.);
|
||||
let historical_ids = [
|
||||
"00000000-0000-0000-0000-00000001adb8",
|
||||
"00000000-0000-0000-0000-00000001adb9",
|
||||
];
|
||||
let historical_reproduced = diagram.id.to_string() == MAIN
|
||||
&& unobscured(&historical_query)
|
||||
&& historical_query["edge_candidates"]
|
||||
.as_array()
|
||||
.is_some_and(|rows| {
|
||||
rows.len() == 2
|
||||
&& historical_ids.iter().all(|id| {
|
||||
rows.iter().any(|r| {
|
||||
r["edge"] == *id
|
||||
&& r["segments"]
|
||||
.as_array()
|
||||
.is_some_and(|s| s.iter().any(|s| s["distance"] == 0.))
|
||||
})
|
||||
})
|
||||
})
|
||||
&& historical_ids.iter().all(|id| {
|
||||
routed
|
||||
.edges
|
||||
.get(&id.parse::<Id>().unwrap())
|
||||
.is_some_and(|e| {
|
||||
e.points.windows(2).any(|p| {
|
||||
p[0].x == 1982.
|
||||
&& p[1].x == 1982.
|
||||
&& p[0].y.min(p[1].y) <= 336.
|
||||
&& p[0].y.max(p[1].y) >= 414.
|
||||
})
|
||||
})
|
||||
});
|
||||
Ok(
|
||||
json!({"experiment":"issue38 geometry probe; not feature acceptance",
|
||||
"experiment_declared_base":"715036e132677dd2bc2fb37ed316d93dc9987aec",
|
||||
"build_provenance":"Require external manifest/source hash verification; this field does not identify the executable build",
|
||||
"diagram":diagram.id,"project":project,
|
||||
"project_conserved":true,"projected_view":view,"routed_edges":edges,
|
||||
"bounds":{"position":routed.bounds.position,"size":routed.bounds.size},
|
||||
"query":query,"alternate_access_samples":alternate,
|
||||
"projected_semantic_inventory":inventory,"declared_answer_key":expected,
|
||||
"historical_witness_reproduced":if diagram.id.to_string()==MAIN {Some(historical_reproduced)} else {None},
|
||||
"historical_witness_policy":"Exact IDs, zero distance at (1982,375), no occluders, common x1982 span336..414 beyond shared port lead; zoom1. False is a result, not failure.",
|
||||
"diagnostics":validation::validate(project)}),
|
||||
)
|
||||
}
|
||||
|
||||
// Bounded reconstruction of routing.rs Rect predicates, not a production API.
|
||||
// The clearance calculation additionally requires exactly orthogonal segments.
|
||||
#[derive(Clone, Copy)]
|
||||
struct LabelProbeRect {
|
||||
left: f32,
|
||||
top: f32,
|
||||
right: f32,
|
||||
bottom: f32,
|
||||
}
|
||||
|
||||
impl LabelProbeRect {
|
||||
fn new(position: Position, size: oa_core::Size) -> Self {
|
||||
Self {
|
||||
left: position.x,
|
||||
top: position.y,
|
||||
right: position.x + size.width,
|
||||
bottom: position.y + size.height,
|
||||
}
|
||||
}
|
||||
|
||||
fn inflate(self, amount: f32) -> Self {
|
||||
Self {
|
||||
left: self.left - amount,
|
||||
top: self.top - amount,
|
||||
right: self.right + amount,
|
||||
bottom: self.bottom + amount,
|
||||
}
|
||||
}
|
||||
|
||||
fn overlaps(self, other: Self) -> bool {
|
||||
self.left < other.right
|
||||
&& self.right > other.left
|
||||
&& self.top < other.bottom
|
||||
&& self.bottom > other.top
|
||||
}
|
||||
|
||||
fn crosses(self, a: Position, b: Position) -> bool {
|
||||
// Keep the source's strict bounds and epsilon, including point segments.
|
||||
const EPSILON: f32 = 0.001;
|
||||
if a == b {
|
||||
return a.x > self.left + EPSILON
|
||||
&& a.x < self.right - EPSILON
|
||||
&& a.y > self.top + EPSILON
|
||||
&& a.y < self.bottom - EPSILON;
|
||||
}
|
||||
if (a.x - b.x).abs() < EPSILON {
|
||||
a.x > self.left + EPSILON
|
||||
&& a.x < self.right - EPSILON
|
||||
&& a.y.min(b.y) < self.bottom - EPSILON
|
||||
&& a.y.max(b.y) > self.top + EPSILON
|
||||
} else if (a.y - b.y).abs() < EPSILON {
|
||||
a.y > self.top + EPSILON
|
||||
&& a.y < self.bottom - EPSILON
|
||||
&& a.x.min(b.x) < self.right - EPSILON
|
||||
&& a.x.max(b.x) > self.left + EPSILON
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn clearance(self, a: Position, b: Position) -> f32 {
|
||||
let dx = (a.x.min(b.x) - self.right)
|
||||
.max(self.left - a.x.max(b.x))
|
||||
.max(0.);
|
||||
let dy = (a.y.min(b.y) - self.bottom)
|
||||
.max(self.top - a.y.max(b.y))
|
||||
.max(0.);
|
||||
dx.hypot(dy)
|
||||
}
|
||||
}
|
||||
|
||||
fn label_candidates(project: &Project, diagram_id: Id, edge_id: Id) -> Result<Value> {
|
||||
let original = project.clone();
|
||||
let diagram = project.diagrams.get(&diagram_id).ok_or("Unknown diagram")?;
|
||||
let view = projection::project_view(project, diagram.id);
|
||||
if view.nodes.iter().any(|node| node.visual_parent.is_some()) {
|
||||
return Err("Label candidate probe supports only flat projected nodes".into());
|
||||
}
|
||||
let routed = routing::route_diagram(project, diagram, &view);
|
||||
let target = routed.edges.get(&edge_id).ok_or("Unknown routed edge")?;
|
||||
if target.custom_suspended
|
||||
|| diagram
|
||||
.routes
|
||||
.iter()
|
||||
.any(|route| route.edge == edge_id && route.label.is_some())
|
||||
{
|
||||
return Err("Label candidate probe requires an automatic, unsuspended label".into());
|
||||
}
|
||||
if target.label.text.is_empty() || target.points.len() < 2 {
|
||||
return Err("Label candidate probe requires nonempty text and a routed path".into());
|
||||
}
|
||||
for edge in routed.edges.values() {
|
||||
if project
|
||||
.relations
|
||||
.get(&edge.id)
|
||||
.is_some_and(|relation| !routing::association_end_geometry(relation, edge).is_empty())
|
||||
{
|
||||
return Err("Label candidate probe does not support association-end labels".into());
|
||||
}
|
||||
if edge.id < edge_id && !edge.label.text.is_empty() {
|
||||
return Err("Label candidate probe does not support earlier nonempty labels".into());
|
||||
}
|
||||
if edge
|
||||
.points
|
||||
.iter()
|
||||
.any(|p| !p.x.is_finite() || !p.y.is_finite())
|
||||
|| edge
|
||||
.points
|
||||
.windows(2)
|
||||
.any(|p| p[0].x != p[1].x && p[0].y != p[1].y)
|
||||
{
|
||||
return Err("Label candidate probe requires finite, exactly orthogonal paths".into());
|
||||
}
|
||||
}
|
||||
// All projected nodes are flat, so edge_obstacles has no traversable ancestors.
|
||||
let obstacles: Vec<_> = view
|
||||
.nodes
|
||||
.iter()
|
||||
.map(|node| LabelProbeRect::new(node.position, node.size).inflate(12.))
|
||||
.collect();
|
||||
// Match record_segments' exact undirected deduplication. Semantic ownership
|
||||
// is reported separately below and must not be lost by this score dedup.
|
||||
let mut strokes: Vec<(Position, Position)> = Vec::new();
|
||||
for edge in routed.edges.values() {
|
||||
for pair in edge.points.windows(2) {
|
||||
let (a, b) = (pair[0], pair[1]);
|
||||
if a != b
|
||||
&& !strokes
|
||||
.iter()
|
||||
.any(|&(x, y)| (x == a && y == b) || (x == b && y == a))
|
||||
{
|
||||
strokes.push((a, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
let size = oa_core::Size {
|
||||
width: target.label.text.chars().count() as f32 * 7. + 16.,
|
||||
height: 24.,
|
||||
};
|
||||
if size != target.label.bounds.size {
|
||||
return Err(
|
||||
"Production label dimensions differ from this experiment's reconstruction".into(),
|
||||
);
|
||||
}
|
||||
let length = |a: Position, b: Position| (b.x - a.x).hypot(b.y - a.y);
|
||||
let total: f32 = target.points.windows(2).map(|p| length(p[0], p[1])).sum();
|
||||
let mut alternatives = vec![0.5_f32];
|
||||
if total > 0. {
|
||||
let mut traversed = 0.;
|
||||
for pair in target.points.windows(2) {
|
||||
let len = length(pair[0], pair[1]);
|
||||
alternatives.push((traversed + len / 2.) / total);
|
||||
traversed += len;
|
||||
}
|
||||
alternatives.extend((1..20).map(|i| i as f32 / 20.));
|
||||
}
|
||||
alternatives.sort_by(|a, b| {
|
||||
(a - 0.5)
|
||||
.abs()
|
||||
.total_cmp(&(b - 0.5).abs())
|
||||
.then_with(|| a.total_cmp(b))
|
||||
});
|
||||
alternatives.dedup();
|
||||
alternatives.truncate(32);
|
||||
let offsets = [
|
||||
Position { x: 0., y: -18. },
|
||||
Position { x: 0., y: 18. },
|
||||
Position { x: 0., y: -46. },
|
||||
Position { x: 0., y: 46. },
|
||||
Position { x: 0., y: -74. },
|
||||
Position { x: 0., y: 74. },
|
||||
Position {
|
||||
x: size.width / 2. + 18.,
|
||||
y: 0.,
|
||||
},
|
||||
Position {
|
||||
x: -size.width / 2. - 18.,
|
||||
y: 0.,
|
||||
},
|
||||
];
|
||||
let mut rows = Vec::new();
|
||||
let mut scores = Vec::new();
|
||||
for offset in offsets {
|
||||
for &fraction in &alternatives {
|
||||
let anchor = routing::point_along_polyline(&target.points, fraction)
|
||||
.ok_or("Missing candidate anchor")?;
|
||||
let center = Position {
|
||||
x: anchor.x + offset.x,
|
||||
y: anchor.y + offset.y,
|
||||
};
|
||||
let position = Position {
|
||||
x: center.x - size.width / 2.,
|
||||
y: center.y - size.height / 2.,
|
||||
};
|
||||
let bounds = LabelProbeRect::new(position, size);
|
||||
let inflated = bounds.inflate(3.);
|
||||
let score = (
|
||||
obstacles
|
||||
.iter()
|
||||
.filter(|obstacle| obstacle.overlaps(bounds))
|
||||
.count(),
|
||||
0_usize,
|
||||
strokes
|
||||
.iter()
|
||||
.filter(|&&(a, b)| inflated.crosses(a, b))
|
||||
.count(),
|
||||
);
|
||||
let mut own_clearance: Option<f32> = None;
|
||||
let mut foreign_clearance: Option<f32> = None;
|
||||
let mut own_intersections = Vec::new();
|
||||
let mut foreign_intersections = Vec::new();
|
||||
for edge in routed.edges.values() {
|
||||
let mut indices = Vec::new();
|
||||
for (index, pair) in edge.points.windows(2).enumerate() {
|
||||
if pair[0] == pair[1] {
|
||||
continue;
|
||||
}
|
||||
let clearance = bounds.clearance(pair[0], pair[1]);
|
||||
let nearest = if edge.id == edge_id {
|
||||
&mut own_clearance
|
||||
} else {
|
||||
&mut foreign_clearance
|
||||
};
|
||||
*nearest = Some(nearest.map_or(clearance, |old| old.min(clearance)));
|
||||
if inflated.crosses(pair[0], pair[1]) {
|
||||
indices.push(index);
|
||||
}
|
||||
}
|
||||
if !indices.is_empty() {
|
||||
let entry = json!({"edge":edge.id,
|
||||
"relation_alias":project.relations.get(&edge.id).map(|r| &r.alias),
|
||||
"segments":indices});
|
||||
if edge.id == edge_id {
|
||||
own_intersections.push(entry);
|
||||
} else {
|
||||
foreign_intersections.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
scores.push(score);
|
||||
rows.push(
|
||||
json!({"fraction":fraction,"offset":offset,"anchor":anchor,"center":center,
|
||||
"bounds":{"position":position,"size":size},"collision_tuple":score,
|
||||
"own_intersections":own_intersections,"foreign_intersections":foreign_intersections,
|
||||
"own_clearance":own_clearance,"foreign_clearance":foreign_clearance}),
|
||||
);
|
||||
}
|
||||
}
|
||||
let best = scores.iter().min().copied().ok_or("No label candidates")?;
|
||||
let best_indices: Vec<_> = scores
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, &score)| (score == best).then_some(index))
|
||||
.collect();
|
||||
if *project != original {
|
||||
return Err("Project changed during label candidate experiment".into());
|
||||
}
|
||||
Ok(
|
||||
json!({"experiment":"issue38 exhaustive f32 label candidate feasibility; not usability acceptance",
|
||||
"scope":"Unbudgeted exhaustive superset of existing candidates. No 8192-comparison budget, early pruning, early exit, or production chooser claim.",
|
||||
"restrictions":"Flat projected nodes, automatic unsuspended nonempty target label, no association-end labels or earlier nonempty labels, finite orthogonal paths.",
|
||||
"geometry_policy":"Source-exact f32 candidate construction and collision predicates: nodes inflated 12; label inflated 3 for stroke intersections; exact undirected stroke deduplication. Clearances use the uninflated label box. Semantic intersection lists retain every distinct edge owner; counts are not the deduplicated collision score.",
|
||||
"build_provenance":"Require external source/build identity; this field does not identify the executable",
|
||||
"diagram":diagram.id,"edge":edge_id,"text":target.label.text,
|
||||
"project":project,"project_conserved":true,"diagnostics":validation::validate(project),
|
||||
"fraction_count":alternatives.len(),"offset_count":offsets.len(),"candidate_count":rows.len(),
|
||||
"distinct_stroke_count":strokes.len(),
|
||||
"zero_node_zero_stroke_count":scores.iter().filter(|score| score.0 == 0 && score.2 == 0).count(),
|
||||
"best_collision_tuple":best,"best_candidate_indices":best_indices,"candidates":rows}),
|
||||
)
|
||||
}
|
||||
|
||||
fn write_new(path: &Path, bytes: &[u8]) -> Result<()> {
|
||||
let mut file = OpenOptions::new().write(true).create_new(true).open(path)?;
|
||||
file.write_all(bytes)?;
|
||||
file.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args: Vec<_> = std::env::args().skip(1).collect();
|
||||
if args.len() == 2 && args[0] == "generate" {
|
||||
// Refuse an existing directory so no previous experiment output is replaced.
|
||||
let out = Path::new(&args[1]);
|
||||
let mixed = admit(MIXED, WARNINGS)?;
|
||||
let eight = representative()?;
|
||||
let scenes = [
|
||||
(
|
||||
"mixed-dispatch",
|
||||
mixed,
|
||||
MAIN,
|
||||
Position { x: 1982., y: 375. },
|
||||
),
|
||||
(
|
||||
"eight-card-representative",
|
||||
eight,
|
||||
EIGHT,
|
||||
Position { x: 600., y: 450. },
|
||||
),
|
||||
];
|
||||
let mut outputs = Vec::new();
|
||||
for (name, project, id, point) in scenes {
|
||||
outputs.push((format!("{name}.json"), serde_json::to_vec_pretty(&project)?));
|
||||
outputs.push((
|
||||
format!("{name}-geometry.json"),
|
||||
serde_json::to_vec_pretty(&snapshot(&project, id.parse()?, point, 1.)?)?,
|
||||
));
|
||||
}
|
||||
fs::create_dir(out)?;
|
||||
write_new(&out.join("mixed-dispatch-original.json"), MIXED)?;
|
||||
write_new(&out.join("release1-original.json"), RELEASE)?;
|
||||
for (name, bytes) in outputs {
|
||||
write_new(&out.join(name), &bytes)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if args.len() == 6 && args[0] == "label-candidates" {
|
||||
let input = fs::read(&args[1])?;
|
||||
let project = admit(&input, &fs::read(&args[2])?)?;
|
||||
let mut result = label_candidates(&project, args[3].parse()?, args[4].parse()?)?;
|
||||
result["original_input_utf8"] = json!(std::str::from_utf8(&input)?);
|
||||
if fs::read(&args[1])? != input {
|
||||
return Err("Input changed during label candidate experiment".into());
|
||||
}
|
||||
result["input_bytes_conserved"] = json!(true);
|
||||
return write_new(Path::new(&args[5]), &serde_json::to_vec_pretty(&result)?);
|
||||
}
|
||||
if args.len() != 8 || args[0] != "probe" {
|
||||
return Err("Usage: generate NEW_DIRECTORY | probe INPUT_JSON_OR_SINGLE_SOURCE EXPECTED_DIAGNOSTICS DIAGRAM_UUID WORLD_X WORLD_Y ZOOM NEW_OUTPUT_JSON | label-candidates INPUT EXPECTED_DIAGNOSTICS DIAGRAM_UUID EDGE_UUID NEW_OUTPUT_JSON".into());
|
||||
}
|
||||
let input = fs::read(&args[1])?;
|
||||
let project = admit(&input, &fs::read(&args[2])?)?;
|
||||
let mut result = snapshot(
|
||||
&project,
|
||||
args[3].parse()?,
|
||||
Position {
|
||||
x: args[4].parse()?,
|
||||
y: args[5].parse()?,
|
||||
},
|
||||
args[6].parse()?,
|
||||
)?;
|
||||
result["original_input_utf8"] = json!(std::str::from_utf8(&input)?);
|
||||
if fs::read(&args[1])? != input {
|
||||
return Err("Input changed during experiment".into());
|
||||
}
|
||||
write_new(Path::new(&args[7]), &serde_json::to_vec_pretty(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn conversation_existing_candidates_cannot_avoid_foreign_allocation() {
|
||||
let project = representative().unwrap();
|
||||
let original = project.clone();
|
||||
let target: Id = "63009b5f-539e-5914-b630-ec6b7fefb4d5".parse().unwrap();
|
||||
let foreign = "725f2e1b-aa2c-5615-9b1f-28da178168fa";
|
||||
let result = label_candidates(&project, EIGHT.parse().unwrap(), target).unwrap();
|
||||
assert_eq!(project, original);
|
||||
assert_eq!(result["project"], serde_json::to_value(&original).unwrap());
|
||||
assert_eq!(result["fraction_count"], 23);
|
||||
assert_eq!(result["candidate_count"], 184);
|
||||
assert_eq!(result["distinct_stroke_count"], 37);
|
||||
assert_eq!(result["zero_node_zero_stroke_count"], 0);
|
||||
assert_eq!(result["best_collision_tuple"], json!([0, 0, 1]));
|
||||
// Independently declared from the saved baseline geometry and a JS
|
||||
// double-precision reconstruction, not generated by this Rust scorer.
|
||||
// Allow f32 interpolation differences without changing the finding.
|
||||
let expected = [
|
||||
(0.5, 274.5),
|
||||
(0.45, 294.8),
|
||||
(0.55, 254.2),
|
||||
(0.6, 233.9),
|
||||
(0.65, 213.6),
|
||||
(0.6761083743842364, 203.),
|
||||
];
|
||||
let near = |value: &Value, expected: f64| {
|
||||
assert!(
|
||||
(value.as_f64().unwrap() - expected).abs() < 0.0002,
|
||||
"{value} differs from declared {expected}"
|
||||
);
|
||||
};
|
||||
let best = result["best_candidate_indices"].as_array().unwrap();
|
||||
assert_eq!(best.len(), expected.len());
|
||||
for (index, (fraction, y)) in best.iter().zip(expected) {
|
||||
let row = &result["candidates"][index.as_u64().unwrap() as usize];
|
||||
near(&row["fraction"], fraction);
|
||||
near(&row["offset"]["x"], 134.5);
|
||||
near(&row["offset"]["y"], 0.);
|
||||
near(&row["center"]["x"], 1296.5);
|
||||
near(&row["center"]["y"], y);
|
||||
near(&row["own_clearance"], 18.);
|
||||
near(&row["foreign_clearance"], 0.);
|
||||
assert_eq!(row["own_intersections"], json!([]));
|
||||
let intersections = row["foreign_intersections"].as_array().unwrap();
|
||||
assert_eq!(intersections.len(), 1);
|
||||
assert_eq!(intersections[0]["edge"], foreign);
|
||||
assert_eq!(intersections[0]["relation_alias"], "sa_repair_allocation");
|
||||
assert_eq!(intersections[0]["segments"], json!([1]));
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn representative_preserves_every_original_record_and_view() {
|
||||
let baseline = admit(RELEASE, RELEASE_WARNINGS).unwrap();
|
||||
let mut generated = representative().unwrap();
|
||||
let added = generated.diagrams.remove(&EIGHT.parse().unwrap()).unwrap();
|
||||
assert_eq!(added.nodes.len(), 8);
|
||||
assert_eq!(generated, baseline);
|
||||
let project = representative().unwrap();
|
||||
let result = snapshot(
|
||||
&project,
|
||||
EIGHT.parse().unwrap(),
|
||||
Position { x: 600., y: 450. },
|
||||
1.,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
result["projected_semantic_inventory"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.len(),
|
||||
12
|
||||
);
|
||||
assert_eq!(
|
||||
result["projected_semantic_inventory"],
|
||||
result["declared_answer_key"]
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn complete_scene_preserves_semantics_sentinel_and_authored_route() {
|
||||
let project = admit(MIXED, WARNINGS).unwrap();
|
||||
let before = project.clone();
|
||||
let id = MAIN.parse().unwrap();
|
||||
let result = snapshot(&project, id, Position { x: 1982., y: 375. }, 1.).unwrap();
|
||||
assert_eq!(project, before);
|
||||
assert_eq!(result["project"], serde_json::to_value(&before).unwrap());
|
||||
assert_eq!(project.diagrams.len(), 2);
|
||||
assert_eq!(
|
||||
result["projected_view"]["nodes"].as_array().unwrap().len(),
|
||||
10
|
||||
);
|
||||
assert_eq!(result["routed_edges"].as_array().unwrap().len(), 14);
|
||||
for edge in result["routed_edges"].as_array().unwrap() {
|
||||
let edge_id: Id = serde_json::from_value(edge["id"].clone()).unwrap();
|
||||
assert_eq!(
|
||||
edge["semantic"]["relation"],
|
||||
serde_json::to_value(&before.relations[&edge_id]).unwrap()
|
||||
);
|
||||
}
|
||||
let route = &before.diagrams[&id].routes[0];
|
||||
assert_eq!(
|
||||
route.edge.to_string(),
|
||||
"00000000-0000-0000-0000-00000001adbd"
|
||||
);
|
||||
assert_eq!(route.waypoints, vec![Position { x: 300., y: -100. }]);
|
||||
assert_eq!(route.label.as_ref().unwrap().fraction, 0.4);
|
||||
assert_eq!(
|
||||
snapshot(&project, id, Position { x: 1982., y: 375. }, 1.).unwrap(),
|
||||
result
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn unexpected_diagnostics_and_invalid_source_fail_closed() {
|
||||
assert!(admit(MIXED, b"[]").is_err());
|
||||
assert!(admit(b"{}", b"[]").is_err());
|
||||
let project = admit(MIXED, WARNINGS).unwrap();
|
||||
assert!(
|
||||
snapshot(
|
||||
&project,
|
||||
MAIN.parse().unwrap(),
|
||||
Position { x: 0., y: 0. },
|
||||
0.
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn square_port_corner_is_occluded_even_outside_ten_unit_circle() {
|
||||
let project = admit(MIXED, WARNINGS).unwrap();
|
||||
let diagram = &project.diagrams[&MAIN.parse().unwrap()];
|
||||
let view = projection::project_view(&project, diagram.id);
|
||||
let routed = routing::route_diagram(&project, diagram, &view);
|
||||
let port = &view.ports[0];
|
||||
let point = Position {
|
||||
x: port.position.x + 9.,
|
||||
y: port.position.y + 9.,
|
||||
};
|
||||
assert!(9_f32.hypot(9.) > 10.);
|
||||
for zoom in [1., 2.] {
|
||||
let hits = candidates(&project, &view, &routed, point, zoom);
|
||||
assert!(hits["port_occluders"].as_array().unwrap().iter()
|
||||
.any(|p| p["element"]==json!(port.element) && p["owner"]==json!(port.owner)));
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn analytical_query_controls_distinguish_edges_segments_and_labels() {
|
||||
// Synthetic geometry controls using genuine identities, NOT witness evidence.
|
||||
let project = admit(MIXED, WARNINGS).unwrap();
|
||||
let diagram = &project.diagrams[&MAIN.parse().unwrap()];
|
||||
let mut view = projection::project_view(&project, diagram.id);
|
||||
let mut routed = routing::route_diagram(&project, diagram, &view);
|
||||
view.nodes.clear();
|
||||
view.ports.clear();
|
||||
let first: Id = "00000000-0000-0000-0000-00000001adb8".parse().unwrap();
|
||||
let second: Id = "00000000-0000-0000-0000-00000001adb9".parse().unwrap();
|
||||
routed.edges.retain(|id, _| *id == first || *id == second);
|
||||
for (id, edge) in &mut routed.edges {
|
||||
edge.points = if *id == first {
|
||||
vec![
|
||||
Position { x: -20., y: 0. },
|
||||
Position { x: 0., y: 0. },
|
||||
Position { x: 0., y: 20. },
|
||||
]
|
||||
} else {
|
||||
vec![Position { x: -20., y: 50. }, Position { x: 20., y: 50. }]
|
||||
};
|
||||
edge.label.text.clear();
|
||||
}
|
||||
let point = Position { x: 0., y: 0. };
|
||||
let hits = candidates(&project, &view, &routed, point, 1.);
|
||||
assert_eq!(hits["edge_candidates"].as_array().unwrap().len(), 1);
|
||||
assert_eq!(
|
||||
hits["edge_candidates"][0]["segments"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
assert!(unobscured(&hits));
|
||||
let edge = routed.edges.get_mut(&second).unwrap();
|
||||
edge.points = vec![Position { x: -20., y: 0. }, Position { x: 20., y: 0. }];
|
||||
edge.label.bounds = routing::RoutingBounds {
|
||||
position: Position { x: -5., y: -5. },
|
||||
size: oa_core::Size {
|
||||
width: 10.,
|
||||
height: 10.,
|
||||
},
|
||||
};
|
||||
edge.label.text = "Control label".into();
|
||||
let hits = candidates(&project, &view, &routed, point, 1.);
|
||||
assert_eq!(hits["edge_candidates"].as_array().unwrap().len(), 2);
|
||||
assert_eq!(hits["label_occluders"], json!([second]));
|
||||
assert!(!unobscured(&hits));
|
||||
routed.edges.get_mut(&second).unwrap().label.text.clear();
|
||||
let hits = candidates(&project, &view, &routed, point, 1.);
|
||||
assert!(hits["label_occluders"].as_array().unwrap().is_empty());
|
||||
assert!(unobscured(&hits));
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,6 @@ async fn press_escape(mounted: &mut Mounted, app: &mut App) -> Vec<Message> {
|
||||
std::slice::from_ref(&input),
|
||||
mouse::Cursor::Unavailable,
|
||||
);
|
||||
assert_eq!(
|
||||
statuses,
|
||||
[iced::event::Status::Captured],
|
||||
"the mounted picker must capture Escape before App subscriptions"
|
||||
);
|
||||
crate::app::escape::tests::subscriptions(app, input, statuses[0], &mut messages);
|
||||
for message in messages.iter().cloned() {
|
||||
let task = app.update(message);
|
||||
@@ -46,11 +41,17 @@ async fn mounted_state_missing_picker_escape_preserves_exact_document_then_reope
|
||||
send(&mut app, Message::BehaviorDiagram(choice));
|
||||
let mut mounted = Mounted::new(&mut app).await;
|
||||
assert_eq!(state_edit::unplaced(app.project(), diagram), vec![f.b]);
|
||||
// Locate the stable picker slot itself: selection controls may sit between
|
||||
// it and the canvas. The single menu option opens below this slot.
|
||||
let bounds = mounted.geometry(&app).bounds("state-missing-picker");
|
||||
let picker = bounds.center();
|
||||
let option = iced::Point::new(picker.x, bounds.y + bounds.height * 1.5);
|
||||
let focus_id = iced::advanced::widget::Id::from("diagram-keyboard-owner");
|
||||
let (_, canvas, _) = mounted
|
||||
.geometry(&app)
|
||||
.focused
|
||||
.into_iter()
|
||||
.find(|(id, _, _)| id.as_ref() == Some(&focus_id))
|
||||
.unwrap();
|
||||
// The existing picker is immediately above the measured canvas, separated
|
||||
// by 8px. Its 12px text and 8px padding give a 31.6px row.
|
||||
let picker = iced::Point::new(canvas.center_x(), canvas.y - 24.);
|
||||
let option = iced::Point::new(picker.x, canvas.y + 8.);
|
||||
let before = app.document.snapshot();
|
||||
let original = app.project().clone();
|
||||
let source = app.document.bundle().clone();
|
||||
|
||||
@@ -187,7 +187,7 @@ pub fn view<'a>(app: &'a App, machine: Id, mut out: Column<'a, Message>) -> Elem
|
||||
.into();
|
||||
out = out.push(
|
||||
column
|
||||
@@ -22,16 +21,7 @@ claim combined Cargo, native, packaged or release acceptance. The independent
|
||||
further material source defect in its stated scope. A subsequent peer compile
|
||||
found a missing `projection::` qualification in the new Route test helper;
|
||||
the current code includes that one-line correction. The original compile failed
|
||||
before running tests. The first combined compile at `897d9f04` subsequently
|
||||
found a missing `text_editor` import in the Allocation Text Apply regression;
|
||||
the current source includes that one-line correction too. Both failures remain
|
||||
recorded in the source handoff. The subsequent full test run at `8ddfadf4`
|
||||
failed the mounted State picker fixture: added selection controls invalidated
|
||||
its canvas-relative clicks. Source successor `a9cd364eacbbffa0693bab05b5a2b65f9d105535`
|
||||
measures an identified fixed-height picker slot and checks Escape capture,
|
||||
retaining the exact preservation/reopen/Place/Undo assertions. The source
|
||||
handoff links the preserved failed and interrupted attempts. Corrected combined
|
||||
Windows execution and package acceptance remain pending.
|
||||
before running tests. Combined execution remains pending.
|
||||
|
||||
Live build, final-source and publication results belong in
|
||||
[issue37](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/37).
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# Small-diagram reading and editing
|
||||
|
||||
Experiment contract for [issue 38](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/38), derived from the user's requirement for intuitive graphical modeling with low cognitive load in [PROJECT_GOAL.md](../PROJECT_GOAL.md). This is a bounded investigation, not acceptance of the application or a routing replacement. Live ownership and dependencies remain in the issue.
|
||||
|
||||
## Evidence and uncertainty
|
||||
|
||||
The user's image contains eight cards and crowded connection corridors despite substantial free space. A selected path is already highlighted. Correctly selecting an edge therefore cannot, by itself, establish that the reported usability problem is solved.
|
||||
|
||||
All displayed names occur in the released `examples/release1` teaching project, but its five saved views do not contain that eight-card arrangement. The original projection, layer identities, positions and authored route overrides are unavailable. Any reconstruction must be labeled representative, with its assumptions stated. It must not be called the user's exact model.
|
||||
|
||||
The existing router already penalizes crossings/shared segments and avoids some label collisions. The editor already highlights selected paths/labels and provides route editing. The investigation must compare actual workflows against these existing capabilities, rather than advertise their presence as a new solution.
|
||||
|
||||
An independently audited historical full-scene witness from the published #32 corpus has ten nodes and fourteen real exchanges. Two edges share a run beyond a common port lead, without node, label or port occlusion at the sampled point. Both have distinct labels and unshared segments elsewhere. This establishes an ambiguous target at that point, **not a globally inaccessible relation**. Regeneration and input through the current application remain necessary; recorded geometry and a picking-helper test are insufficient.
|
||||
|
||||
The [probe, fixtures and independent source review](experiments/diagram-readability-20260929/README.md) make those assumptions executable. Review corrected an initial port-hit radius assumption, a five-edge omission from the representative answer key and an incomplete warning baseline. [Current-router execution](experiments/diagram-readability-20260929/run-results.md) passes five tests and reproduces the historical overlap without changing the model. The mixed-layer eight-card view has twelve actual relationships and uses Traceability, which flattens visual parents; it is not evidence for nested/folded controls. Native reading/editing workflows remain a separate gate.
|
||||
|
||||
## Alternatives and decision boundary
|
||||
|
||||
Criteria are correct relationship identity, useful direct editing, readable paths and labels at working scale, preserved authored intent, predictable latency, and maintainable scope.
|
||||
|
||||
| Candidate | Useful outcome | Reason to reject or defer |
|
||||
| --- | --- | --- |
|
||||
| Explicit choice at ambiguous connection hits | Deliberately target an overlapping edge without moving the model | Ordinary clicks become cumbersome; selected-edge bend/label editing is intercepted; it merely prints answers while the diagram remains unreadable |
|
||||
| Local route/label separation | Trace connections without confusing shared runs or detached labels | Authored pins/ports change, unrelated routes regress, occupied area makes Fit unreadable, or expensive rerouting harms interaction |
|
||||
| Existing focused views | Answer a scoped engineering question with fewer unrelated lines | Hides a required relation or substitutes filtering for the ability to edit the complete small view |
|
||||
| Selected-label association cue | Associate a displaced label with its highlighted edge | Adds visual noise, conceals nearby content, or fails to address the demonstrated tracing errors |
|
||||
|
||||
No implementation candidate is accepted yet. First perform a complete-scene identify/select/repair/undo task and a create-connection task. If targetability is already adequate but tracing fails, prioritize association/separation evidence over additional selection machinery. Any narrow improvement leaves the wider readability gate open until measured directly.
|
||||
|
||||
Capella supports local label alignment/reset and a selected edge-to-label attachment cue ([official layout guide](https://github.com/eclipse-capella/capella/blob/master/doc/plugins/org.polarsys.capella.tipsandtricks.doc/html/Tips%20and%20tricks/8_Other%20layout%20facilities/8_Other%20layout%20facilities.mediawiki)). Sirius distinguishes crossing jump marks from label attachment links ([official diagram guide](https://eclipse.dev/sirius/doc/user/diagrams/Diagrams.html)). These provide comparable local repair tools; neither establishes that a chooser or jump mark solves long coincident paths in this application.
|
||||
|
||||
## Evaluator
|
||||
|
||||
Freeze fixture bytes, source/build, semantic IDs and endpoint answer key, projection, authored routes, camera/window size and an untouched sentinel view before the run. Preserve failed attempts. Include disjoint, crossing, coincident/opposed, near-coincident, shared-endpoint, long/identical-label, fixed-port and nested/folded controls. Do not silently simplify a scene until its failure disappears.
|
||||
|
||||
1. **Read:** trace requested relations and identify their endpoints in the complete diagram before showing an answer-bearing Inspector/chooser. Record wrong turns, ambiguous labels/arrowheads, time and recovery actions. Keep this separate from lookup accuracy.
|
||||
2. **Select:** deliberately reach each competing actual relation at the ambiguous location. Check positive controls at its unique label/unshared segment. Ordinary one-target points stay direct. Selection and cancellation preserve model, history, view and layer. Exercise left click, context targeting and group admission independently.
|
||||
3. **Draw:** create an intended valid relationship in the populated scene, then identify and edit the new connection. Check refused endpoints and cancellation with no unintended relation or history transaction.
|
||||
4. **Repair:** move one label, add/move/remove a bend and adjust an eligible attachment. Compare the complete Project against independently declared changes. Semantic endpoints, port ownership, other authored routes and sentinel views remain exact. A gesture commits once; Undo/Redo and save/reopen recover exact authored state.
|
||||
5. **Recover:** Escape, Help, focus departure, view/projection changes and stale queued input must not commit unintended geometry or retain a held gesture. Failed source/model validation preserves the prior state and redo.
|
||||
6. **Measure:** report shared-run length per distinct edge pair, nonincident contacts, crossings, node penetrations, label/node/stroke overlap, label association distance, occupied area, Fit scale and action latency separately. Include screen-space near overlaps; world-coordinate separation alone can remain unreadable. Do not hide regressions in one weighted score.
|
||||
|
||||
The router deliberately freezes other edges during a route preview, then allows automatic paths/labels to settle on commit. Preserve semantic and authored-field equality; record and assess that visual settlement instead of assuming whole-scene preview equality. Evaluate translation and UUID variants so a favorable identity/order does not become the claimed algorithmic result.
|
||||
|
||||
## Implementation boundaries
|
||||
|
||||
Ports, nodes, selected attachments/bends/labels and group selection can intercept input before ordinary edge picking. A helper-only change does not cover the production workflow. Any candidates must deduplicate by semantic edge identity, distinguish semantic endpoints from folded visual endpoints, retain captured document/diagram/revision validation, and remain observational until an explicit model or geometry edit.
|
||||
|
||||
The existing selected-edge tie preference supports direct dragging; do not replace it with unconditional cycling. A transient ambiguity preview must not create a bend or apply a pending property draft. Coordinate contextual selection with #43 and performance with #44. This investigation does not resume the paused #32 planner or absorb the separate #40 allocation-drag and #41 palette contributions.
|
||||
@@ -1,3 +0,0 @@
|
||||
# Preserve checksum-bound fixtures and provenance through Git round trips.
|
||||
*.json -text whitespace=cr-at-eol
|
||||
run-f754/*.log -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
@@ -1,115 +0,0 @@
|
||||
# Issue 38 bounded geometry experiment
|
||||
|
||||
Core source baseline `715036e132677dd2bc2fb37ed316d93dc9987aec`. The parent compiled
|
||||
the probe at `2aac3e83532166dc45cd3519cc5d89b3e84d57f3`; its first test run passed
|
||||
one test and failed four at admission because the expected warning baseline was
|
||||
incomplete. The corrected baseline awaits rerun; geometry generation did not run.
|
||||
No GUI selection or feature acceptance is claimed. The parent owns execution and
|
||||
publication. Windows only; Linux/WSL excluded.
|
||||
|
||||
The Rust example uses `persistence::decode`, `validation::validate`,
|
||||
`projection::project_view`, and `routing::route_diagram`. It accepts schema JSON or
|
||||
single-file Arcadia source, not a multi-file source bundle. No production modules
|
||||
are changed. It records the complete admitted Project, all projected nodes/ports/
|
||||
edges, semantic endpoint identities, authored and effective route data, settled
|
||||
geometry, labels, warnings, query occluders, and alternate geometric samples.
|
||||
Its input source is read-only. Generation preserves original input bytes alongside
|
||||
normalized complete projects. Individual probe output includes the exact UTF-8
|
||||
input. Output files use create-new, and generation refuses an existing directory.
|
||||
|
||||
## Inputs and independent answer keys
|
||||
|
||||
`mixed-dispatch-original.json` is the exact 32,787-byte archived corpus member
|
||||
`inputs/corpus/mixed_dispatch.json` (see provenance hashes). It has ten function
|
||||
cards, fourteen Functional Exchanges, two saved views, and authored feedback route
|
||||
`...01adbd` with waypoint `(300,-100)`, label fraction `.4`, offset `(-30,-70)`.
|
||||
The secondary view is a conservation sentinel. The original full archive is
|
||||
linked/hashes recorded in `provenance.json`; it is not duplicated here. Only the
|
||||
historical **before** geometry from producer `3e21c1bc...` informed the declared
|
||||
query. The paused boundary-order planner is neither imported nor executed.
|
||||
|
||||
`eight-card-view.json` adds one view to the complete, unchanged
|
||||
`examples/release1/model.json`. Its positions approximate the user's screenshot;
|
||||
the exact saved user view/camera/pins have not been recovered. The mixed OA Process
|
||||
and SA cards use an inferred SA/Traceability view, not SA/Overview. This is a
|
||||
representative reconstruction, not proof of the original projection or identities.
|
||||
No authored routes are invented. All five original views remain unchanged.
|
||||
|
||||
The fixed answer keys were derived from input semantic records and endpoint-owner
|
||||
placements, independently of the router. `eight-answer-key.json` has **12** edges:
|
||||
four Allocation, four PortAllocation, two FunctionalExchange, one BoundaryExchange,
|
||||
and one OA ChainInvolvement. No traces have both endpoints shown. PortAllocation
|
||||
and BoundaryExchange semantic endpoints are ports; projected endpoints are their
|
||||
owner placements. `mixed-answer-key.json` has fourteen FunctionalExchanges.
|
||||
The probe fails if a recognized fixture view's full projected inventory differs,
|
||||
including kind, semantic endpoints, ports, projected endpoints, and trace flag.
|
||||
Do not treat the eight-card count alone as a semantic acceptance check.
|
||||
|
||||
The explicit archived warning baseline is **60**: ten `work_without_behavior_context`,
|
||||
fourteen `exchange_without_behavior_context`, one `missing_system`, and ten
|
||||
`unallocated_leaf`, and 25 `empty_port_contract` diagnostics. The first 24-warning
|
||||
baseline omitted the last three families. [The correction review](warning-baseline-review.md) derives their
|
||||
identities, fields, and messages independently from input records and validation
|
||||
rules; it does not regenerate expectations from observed diagnostics. The release1 baseline is its
|
||||
existing one-warning `expected-diagnostics.json`. Every error, missing warning,
|
||||
extra warning, or changed warning field/message fails admission. No automatic
|
||||
warning acceptance or migration-based fixture replacement is performed.
|
||||
|
||||
## Query policy and limits
|
||||
|
||||
The declared historical query is world `(1982,375)`, zoom `1`. Reproduction requires
|
||||
exactly the two genuine edges `...01adb8` (Actuator dispatch) and `...01adb9`
|
||||
(Operator dispatch copy), zero segment distance, no node/port/label occluder,
|
||||
and common vertical x1982 span y336..414 beyond the common port lead. The flag is
|
||||
false when current routing no longer reproduces this geometry; that is a valid
|
||||
experiment result, not an implementation failure. The eight-card default query
|
||||
`(600,450)` is merely a declared inspection point, not an asserted overlap witness.
|
||||
|
||||
Line candidates use seven screen pixels converted to world units. Port occlusion
|
||||
uses the desktop's **axis-aligned square** half-width `max(10/zoom,10)` world units.
|
||||
It is not a radius-eight circle: `(9,9)` relative to a port center is inside the
|
||||
square at zoom1 and zoom2 although its Euclidean distance exceeds10. The earlier
|
||||
local historical audit's radius-eight assumption is superseded; its original
|
||||
record remains historical and must not be cited as the current port-policy proof.
|
||||
Node rectangles, nonempty ordinary label rectangles, and association-end label
|
||||
rectangles are reported independently. Candidates are distinct edge identities,
|
||||
with every matching segment recorded; a bend does not count as two edges.
|
||||
|
||||
Alternate access is a conservative sample at each segment's quarter/middle/three-
|
||||
quarter points and each label center across the complete scene. A positive result
|
||||
identifies geometric access under this query policy; a negative result proves
|
||||
nothing about global accessibility. Native selected handles, gesture state,
|
||||
viewport clipping, Inspector selection, keyboard behavior, pan/redraw, and actual
|
||||
input dispatch are excluded. Ordinary labels precede association labels in desktop
|
||||
dispatch; this probe conservatively rejects either overlap for an unoccluded sample.
|
||||
It never claims native selection or global inaccessibility.
|
||||
|
||||
Read-only Project equality is a capture/conservation control, not an edit/undo test.
|
||||
Neither automatic route stability after edits nor preview/committed settlement
|
||||
identity is promised. Native evaluation must separately cover unaided tracing,
|
||||
assisted selection, creating an intended relation in the populated scene, moving
|
||||
labels/connections, undo/redo, save/reload, and preservation of authored metadata.
|
||||
Inherited navigation defects (#43) must be recorded separately from routing (#38).
|
||||
|
||||
## Run and review
|
||||
|
||||
The first completed current-router run at `f754ad85` passes all five tests and
|
||||
both generation/query commands. [Results and independent interpretation](run-results.md)
|
||||
link exact artifacts and retained warning-baseline failures. Native workflows
|
||||
and any production improvement remain unverified.
|
||||
|
||||
From the pinned worktree, with a fresh output path:
|
||||
|
||||
```powershell
|
||||
cargo test --locked -p oa-core --example diagram_readability_probe
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- generate .local/issue38-probe-run01
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- probe harness/experiments/diagram-readability-20260929/mixed-dispatch-original.json harness/experiments/diagram-readability-20260929/mixed-dispatch-expected-diagnostics.json 00000000-0000-0000-0000-0000000186a1 1982 375 1 .local/issue38-probe-query01.json
|
||||
```
|
||||
|
||||
Record `git rev-parse HEAD`, local diff, executable hash, Rust version, commands,
|
||||
stdout/stderr, and output hashes. Verify `provenance.json` source/input SHA256s before
|
||||
making a pinned-router claim. The output's declared base is not executable identity.
|
||||
Tests check original-project conservation, full semantic inventories, sentinel and
|
||||
authored route preservation, deterministic snapshots, failed admission, the port
|
||||
corner, and analytical distinct-edge/label controls. Reuse current generated
|
||||
geometry for subsequent native work; do not relabel historical geometry as a new run.
|
||||
@@ -1,134 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "09eaa992-4cdf-5ea3-b748-f10fd74b8cba",
|
||||
"kind": "PortAllocation",
|
||||
"source": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"target": "d2113fb0-a531-54ef-9484-13951b00ab8f",
|
||||
"source_port": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"target_port": "d2113fb0-a531-54ef-9484-13951b00ab8f",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000102",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000105",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "3cc9ab52-2b00-57fd-8709-aabc75e5d3e3",
|
||||
"kind": "Allocation",
|
||||
"source": "435bf87c-73fd-5e4d-978a-4c471bc9eaf0",
|
||||
"target": "09342ccb-044b-5483-ac58-87dc3cf7831c",
|
||||
"source_port": null,
|
||||
"target_port": null,
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000106",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "55ec4dbf-bd17-5b0c-b3a3-95b2194aa8b9",
|
||||
"kind": "PortAllocation",
|
||||
"source": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target": "24a6850e-b819-57e0-af88-ca4ab76581b7",
|
||||
"source_port": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target_port": "24a6850e-b819-57e0-af88-ca4ab76581b7",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000103",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "568c5c01-de21-52a2-83bd-afdddc158085",
|
||||
"kind": "PortAllocation",
|
||||
"source": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target": "391af7c4-b07d-53a7-8ddd-5c81461fc4f8",
|
||||
"source_port": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target_port": "391af7c4-b07d-53a7-8ddd-5c81461fc4f8",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000108",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "628cb4fc-fe63-5f6b-b364-6268f26b5740",
|
||||
"kind": "ChainInvolvement",
|
||||
"source": "022d3cfa-bbaf-5e13-924a-8e55099b8745",
|
||||
"target": "6a30b763-cc51-546d-907f-5c63657cfd03",
|
||||
"source_port": null,
|
||||
"target_port": null,
|
||||
"projected_source": "00000000-0038-4000-8000-000000000101",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000107",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "63009b5f-539e-5914-b630-ec6b7fefb4d5",
|
||||
"kind": "BoundaryExchange",
|
||||
"source": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"source_port": "98d411e7-7c65-5c3f-b543-8bf0f2522ea2",
|
||||
"target_port": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000102",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "684eadc3-e670-5779-a60f-bbc9a5bfb062",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "9497e10f-04c4-5586-8738-2464a6f00bd4",
|
||||
"target": "d75eb3fa-a27d-52d5-8782-8b342b3865f6",
|
||||
"source_port": "994faed7-dbc8-5b96-9d62-7604ac0fbc3a",
|
||||
"target_port": "391af7c4-b07d-53a7-8ddd-5c81461fc4f8",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000105",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000108",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"kind": "Allocation",
|
||||
"source": "c05b9422-b9da-5de5-b21d-07ad23bd2b8a",
|
||||
"target": "9497e10f-04c4-5586-8738-2464a6f00bd4",
|
||||
"source_port": null,
|
||||
"target_port": null,
|
||||
"projected_source": "00000000-0038-4000-8000-000000000102",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000105",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "93474111-f23e-56c1-b61b-b7c2396b91bd",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "dddae020-a444-5d48-acc8-139d2696a672",
|
||||
"target": "9497e10f-04c4-5586-8738-2464a6f00bd4",
|
||||
"source_port": "24a6850e-b819-57e0-af88-ca4ab76581b7",
|
||||
"target_port": "d2113fb0-a531-54ef-9484-13951b00ab8f",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000103",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000105",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "9b9356d7-2db2-5a94-a47e-ea892cf02afe",
|
||||
"kind": "Allocation",
|
||||
"source": "435bf87c-73fd-5e4d-978a-4c471bc9eaf0",
|
||||
"target": "dddae020-a444-5d48-acc8-139d2696a672",
|
||||
"source_port": null,
|
||||
"target_port": null,
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000103",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "b76bf8de-2fa4-563f-a540-dd30f30e6c49",
|
||||
"kind": "Allocation",
|
||||
"source": "435bf87c-73fd-5e4d-978a-4c471bc9eaf0",
|
||||
"target": "d75eb3fa-a27d-52d5-8782-8b342b3865f6",
|
||||
"source_port": null,
|
||||
"target_port": null,
|
||||
"projected_source": "00000000-0038-4000-8000-000000000104",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000108",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "e53b7a40-e8a3-5b3f-826d-c2b5c164a84a",
|
||||
"kind": "PortAllocation",
|
||||
"source": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"target": "994faed7-dbc8-5b96-9d62-7604ac0fbc3a",
|
||||
"source_port": "e6d69cbd-99d7-596b-bbe3-dada6118a600",
|
||||
"target_port": "994faed7-dbc8-5b96-9d62-7604ac0fbc3a",
|
||||
"projected_source": "00000000-0038-4000-8000-000000000102",
|
||||
"projected_target": "00000000-0038-4000-8000-000000000105",
|
||||
"trace": false
|
||||
}
|
||||
]
|
||||
@@ -1,132 +0,0 @@
|
||||
{
|
||||
"id": "00000000-0038-4000-8000-000000000001",
|
||||
"alias": "issue38_representative_mixed",
|
||||
"name": "Issue 38 representative eight-card mixed view",
|
||||
"description": "Research approximation of screenshot positions; not recovered user source. Traceability inferred from OA Process with SA Functions. No authored routes inferred.",
|
||||
"layer": "Sa",
|
||||
"projection": "Traceability",
|
||||
"nodes": {
|
||||
"00000000-0038-4000-8000-000000000101": {
|
||||
"id": "00000000-0038-4000-8000-000000000101",
|
||||
"alias": "issue38_oa_assessment_procedure",
|
||||
"element": "022d3cfa-bbaf-5e13-924a-8e55099b8745",
|
||||
"position": {
|
||||
"x": 314,
|
||||
"y": 40
|
||||
},
|
||||
"size": {
|
||||
"width": 243,
|
||||
"height": 101
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000102": {
|
||||
"id": "00000000-0038-4000-8000-000000000102",
|
||||
"alias": "issue38_sa_technician",
|
||||
"element": "c05b9422-b9da-5de5-b21d-07ad23bd2b8a",
|
||||
"position": {
|
||||
"x": 1180,
|
||||
"y": 18
|
||||
},
|
||||
"size": {
|
||||
"width": 265,
|
||||
"height": 143
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000103": {
|
||||
"id": "00000000-0038-4000-8000-000000000103",
|
||||
"alias": "issue38_sa_assess",
|
||||
"element": "dddae020-a444-5d48-acc8-139d2696a672",
|
||||
"position": {
|
||||
"x": 54,
|
||||
"y": 245
|
||||
},
|
||||
"size": {
|
||||
"width": 265,
|
||||
"height": 143
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000104": {
|
||||
"id": "00000000-0038-4000-8000-000000000104",
|
||||
"alias": "issue38_sa_control",
|
||||
"element": "435bf87c-73fd-5e4d-978a-4c471bc9eaf0",
|
||||
"position": {
|
||||
"x": 736,
|
||||
"y": 245
|
||||
},
|
||||
"size": {
|
||||
"width": 265,
|
||||
"height": 143
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000105": {
|
||||
"id": "00000000-0038-4000-8000-000000000105",
|
||||
"alias": "issue38_sa_repair",
|
||||
"element": "9497e10f-04c4-5586-8738-2464a6f00bd4",
|
||||
"position": {
|
||||
"x": 1083,
|
||||
"y": 343
|
||||
},
|
||||
"size": {
|
||||
"width": 266,
|
||||
"height": 143
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000106": {
|
||||
"id": "00000000-0038-4000-8000-000000000106",
|
||||
"alias": "issue38_sa_reset",
|
||||
"element": "09342ccb-044b-5483-ac58-87dc3cf7831c",
|
||||
"position": {
|
||||
"x": 227,
|
||||
"y": 516
|
||||
},
|
||||
"size": {
|
||||
"width": 266,
|
||||
"height": 119
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000107": {
|
||||
"id": "00000000-0038-4000-8000-000000000107",
|
||||
"alias": "issue38_oa_triage",
|
||||
"element": "6a30b763-cc51-546d-907f-5c63657cfd03",
|
||||
"position": {
|
||||
"x": 1317,
|
||||
"y": 581
|
||||
},
|
||||
"size": {
|
||||
"width": 243,
|
||||
"height": 103
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"00000000-0038-4000-8000-000000000108": {
|
||||
"id": "00000000-0038-4000-8000-000000000108",
|
||||
"alias": "issue38_sa_confirm",
|
||||
"element": "d75eb3fa-a27d-52d5-8782-8b342b3865f6",
|
||||
"position": {
|
||||
"x": 227,
|
||||
"y": 689
|
||||
},
|
||||
"size": {
|
||||
"width": 266,
|
||||
"height": 143
|
||||
},
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
"routes": [],
|
||||
"view_options": {
|
||||
"work_contexts": "All",
|
||||
"participant_categories": "All",
|
||||
"coverage": "All",
|
||||
"hidden_edges": [],
|
||||
"exchange_labels": "Name",
|
||||
"work_categories": "All",
|
||||
"relation_kinds": "All"
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb0",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018704",
|
||||
"target": "00000000-0000-0000-0000-000000018708",
|
||||
"source_port": "edb626b5-7d99-5015-9faf-71a06232d86e",
|
||||
"target_port": "ebfcf690-4ac5-5976-864c-337d844b6cd6",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018705",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018709",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb1",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018706",
|
||||
"target": "00000000-0000-0000-0000-000000018708",
|
||||
"source_port": "d9647cdb-2fcd-5b3f-94b4-ed2a3b8ebf66",
|
||||
"target_port": "ebfcf690-4ac5-5976-864c-337d844b6cd6",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018707",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018709",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb2",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018708",
|
||||
"target": "00000000-0000-0000-0000-00000001870a",
|
||||
"source_port": "9244d718-d53a-54cb-a920-5b5312576da6",
|
||||
"target_port": "14c74a31-2041-59ac-877a-bc8aa0548896",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018709",
|
||||
"projected_target": "00000000-0000-0000-0000-00000001870b",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb3",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018708",
|
||||
"target": "00000000-0000-0000-0000-00000001870c",
|
||||
"source_port": "9244d718-d53a-54cb-a920-5b5312576da6",
|
||||
"target_port": "fe1b5efc-983a-593c-a02f-affd40ff5a2f",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018709",
|
||||
"projected_target": "00000000-0000-0000-0000-00000001870d",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb4",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-00000001870a",
|
||||
"target": "00000000-0000-0000-0000-00000001870e",
|
||||
"source_port": "b4b5d6dc-a2b2-59b0-8898-32dc2e7aa906",
|
||||
"target_port": "d865e245-0fe6-5c21-a872-d57863a1f857",
|
||||
"projected_source": "00000000-0000-0000-0000-00000001870b",
|
||||
"projected_target": "00000000-0000-0000-0000-00000001870f",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb5",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-00000001870c",
|
||||
"target": "00000000-0000-0000-0000-00000001870e",
|
||||
"source_port": "f9d7dbf7-a221-5e51-a58f-530d4ca176e7",
|
||||
"target_port": "51641731-5387-5d58-9bcb-2074acdbe23d",
|
||||
"projected_source": "00000000-0000-0000-0000-00000001870d",
|
||||
"projected_target": "00000000-0000-0000-0000-00000001870f",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb6",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-00000001870e",
|
||||
"target": "00000000-0000-0000-0000-000000018710",
|
||||
"source_port": "224d8f5f-2a81-5315-b7b6-24fe0cd9e95d",
|
||||
"target_port": "406e76e5-affd-59a2-bf1b-c3b3b22d3dd2",
|
||||
"projected_source": "00000000-0000-0000-0000-00000001870f",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018711",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb7",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018710",
|
||||
"target": "00000000-0000-0000-0000-000000018712",
|
||||
"source_port": "8661fe68-51aa-5c8c-827f-e7abea0f6b66",
|
||||
"target_port": "1c6a0a70-81b3-5c39-a2fd-c3d5b9a112c0",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018711",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018713",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb8",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018712",
|
||||
"target": "00000000-0000-0000-0000-000000018714",
|
||||
"source_port": "169224b3-b692-540d-ac73-1435e2a87b04",
|
||||
"target_port": "b1949371-949b-5cb5-acab-485dc4de2e80",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018713",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018715",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adb9",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018712",
|
||||
"target": "00000000-0000-0000-0000-000000018716",
|
||||
"source_port": "169224b3-b692-540d-ac73-1435e2a87b04",
|
||||
"target_port": "01abf25b-82c2-51bc-adbc-73cf6f411b2d",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018713",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018717",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adba",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018716",
|
||||
"target": "00000000-0000-0000-0000-000000018714",
|
||||
"source_port": "bbee14f0-a8d5-5a0d-90e3-01f2d4c5e088",
|
||||
"target_port": "e9dc0338-4237-5cc0-9e7f-7031b51c4772",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018717",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018715",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adbb",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-00000001870c",
|
||||
"target": "00000000-0000-0000-0000-000000018714",
|
||||
"source_port": "7d27cb1e-8dc7-5ebe-9407-a1d05e547562",
|
||||
"target_port": "193bd9b2-e1dd-5764-8f41-777884d3a5ea",
|
||||
"projected_source": "00000000-0000-0000-0000-00000001870d",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018715",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adbc",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018706",
|
||||
"target": "00000000-0000-0000-0000-00000001870c",
|
||||
"source_port": "2fcb392a-80e8-5be4-990c-79de2be0a19b",
|
||||
"target_port": "fdf21c35-cd98-5e9a-9a35-faa453f137ca",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018707",
|
||||
"projected_target": "00000000-0000-0000-0000-00000001870d",
|
||||
"trace": false
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-0000-0000-00000001adbd",
|
||||
"kind": "FunctionalExchange",
|
||||
"source": "00000000-0000-0000-0000-000000018710",
|
||||
"target": "00000000-0000-0000-0000-000000018704",
|
||||
"source_port": "6f72f5b2-e6c2-5700-a7d5-f945d076fcb8",
|
||||
"target_port": "e3f59e03-53c7-5d99-97f0-f52542e939c7",
|
||||
"projected_source": "00000000-0000-0000-0000-000000018711",
|
||||
"projected_target": "00000000-0000-0000-0000-000000018705",
|
||||
"trace": false
|
||||
}
|
||||
]
|
||||
@@ -1,422 +0,0 @@
|
||||
[
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018704",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018706",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018708",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870a",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870c",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870e",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018710",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018712",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018714",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Include this leaf activity/function in a process/chain or scenario through a work action or exchange occurrence.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018716",
|
||||
"code": "work_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb0",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb1",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb2",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb3",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb4",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb5",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb6",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb7",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb8",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adb9",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adba",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adbb",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adbc",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"message": "Use this exchange in a process/chain or scenario.",
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001adbd",
|
||||
"code": "exchange_without_behavior_context",
|
||||
"field": null
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-0000000186a0",
|
||||
"code": "missing_system",
|
||||
"field": "elements",
|
||||
"message": "Identify the SA system of interest."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018704",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Sensor A' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018706",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Sensor B' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018708",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Ingest' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870a",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Validate' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870c",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Archive' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-00000001870e",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Correlate' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018710",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Plan' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018712",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Dispatch' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018714",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Actuator' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "00000000-0000-0000-0000-000000018716",
|
||||
"code": "unallocated_leaf",
|
||||
"field": "allocation",
|
||||
"message": "Allocate leaf 'Operator' to a performer."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "01abf25b-82c2-51bc-adbc-73cf6f411b2d",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "14c74a31-2041-59ac-877a-bc8aa0548896",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "169224b3-b692-540d-ac73-1435e2a87b04",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "193bd9b2-e1dd-5764-8f41-777884d3a5ea",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "1c6a0a70-81b3-5c39-a2fd-c3d5b9a112c0",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "224d8f5f-2a81-5315-b7b6-24fe0cd9e95d",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "2fcb392a-80e8-5be4-990c-79de2be0a19b",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "406e76e5-affd-59a2-bf1b-c3b3b22d3dd2",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "51641731-5387-5d58-9bcb-2074acdbe23d",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "6f72f5b2-e6c2-5700-a7d5-f945d076fcb8",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "7d27cb1e-8dc7-5ebe-9407-a1d05e547562",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "8661fe68-51aa-5c8c-827f-e7abea0f6b66",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "9244d718-d53a-54cb-a920-5b5312576da6",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "b1949371-949b-5cb5-acab-485dc4de2e80",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "b4b5d6dc-a2b2-59b0-8898-32dc2e7aa906",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "bbee14f0-a8d5-5a0d-90e3-01f2d4c5e088",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "d865e245-0fe6-5c21-a872-d57863a1f857",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "d9647cdb-2fcd-5b3f-94b4-ed2a3b8ebf66",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "e3f59e03-53c7-5d99-97f0-f52542e939c7",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "e9dc0338-4237-5cc0-9e7f-7031b51c4772",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "ebfcf690-4ac5-5976-864c-337d844b6cd6",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "edb626b5-7d99-5015-9faf-71a06232d86e",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "f9d7dbf7-a221-5e51-a58f-530d4ca176e7",
|
||||
"code": "empty_port_contract",
|
||||
"field": "outgoing_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "fdf21c35-cd98-5e9a-9a35-faa453f137ca",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
},
|
||||
{
|
||||
"severity": "Warning",
|
||||
"element": "fe1b5efc-983a-593c-a02f-affd40ff5a2f",
|
||||
"code": "empty_port_contract",
|
||||
"field": "incoming_items",
|
||||
"message": "This function port has no declared exchange items."
|
||||
}
|
||||
]
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"declared_base": "715036e132677dd2bc2fb37ed316d93dc9987aec",
|
||||
"status": "Completed Windows current-router run at f754ad85d3674a709d10054e6fe23079f977c547: formatting, five tests, generation and separate query pass. Initial failed24 run preserved; native workflows remain unverified. See run-results.md and run-f754/receipt.json.",
|
||||
"files": [
|
||||
{
|
||||
"path": "crates/oa-core/src/model.rs",
|
||||
"bytes": 68387,
|
||||
"sha256": "05a6bd5eef14c77e7cafd2bc72eb3bb6b19f33c6d06184b4e7d21173a2684078"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/persistence.rs",
|
||||
"bytes": 31774,
|
||||
"sha256": "1c01474f906a63e552c0d590b272c95821c00a100b3e79e58e67dbbeac341a14"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/projection.rs",
|
||||
"bytes": 21687,
|
||||
"sha256": "3521bf3041502f3a3a970d7799894a5ae16c1e8da754deeea5290ac1f8ba11e8"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/routing.rs",
|
||||
"bytes": 53958,
|
||||
"sha256": "b377fe80cece3892d64f62ba5e1578d8974eeefc2a317620f343a86f2f257fbd"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/routing/attachments.rs",
|
||||
"bytes": 5918,
|
||||
"sha256": "cfb4200cdb99e4d86eb6e5ac1b123e4075fb7d4c788860d154365ad8ece139d7"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/projection/port_layout.rs",
|
||||
"bytes": 13474,
|
||||
"sha256": "a08d17d10a58bb8b206dd001b19b91d5aa3a9f743b298a4da57d503223c20079"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/validation.rs",
|
||||
"bytes": 113436,
|
||||
"sha256": "f440bfe0f6493e5155eb377eaa766f903abea6006c02325a4b1f09a0b349b8f8"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/validation/coverage.rs",
|
||||
"bytes": 6478,
|
||||
"sha256": "b08e4b344ecad055714168c83beff7fe29ba4edc53edbffa2eae04e5580a4d5f"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/diagram.rs",
|
||||
"bytes": 124738,
|
||||
"sha256": "3170397b82236d6db2a57a1bb860c3c44fd8ec16172701e6784d4bf1314d140f"
|
||||
},
|
||||
{
|
||||
"path": "examples/release1/model.json",
|
||||
"bytes": 134520,
|
||||
"sha256": "ef0ef4006c3e09d5db6e1b621256b3f7d6642f3a7b09cc34607cfbcca830c727"
|
||||
},
|
||||
{
|
||||
"path": "harness/experiments/diagram-readability-20260929/mixed-dispatch-original.json",
|
||||
"bytes": 32787,
|
||||
"sha256": "81d25af021cbad18af4262a220ba60372e51ca19083b7e80f2b19196baf05990"
|
||||
},
|
||||
{
|
||||
"path": "harness/experiments/diagram-readability-20260929/eight-card-view.json",
|
||||
"bytes": 3641,
|
||||
"sha256": "f851e7e96fc6f5b1edb328b94eb991aa8e94b14cc1bcd07b2c42d32310c4527b"
|
||||
},
|
||||
{
|
||||
"path": "harness/experiments/diagram-readability-20260929/mixed-dispatch-expected-diagnostics.json",
|
||||
"bytes": 14337,
|
||||
"sha256": "be6747f4bec4f285b411dfbc934ab63ee46e64403354652d73ec7a801d1c0b2d"
|
||||
},
|
||||
{
|
||||
"path": "harness/experiments/diagram-readability-20260929/mixed-answer-key.json",
|
||||
"bytes": 6683,
|
||||
"sha256": "1696f06e8a4099c2863ad6a5c444ca41ade0848a183b7cd8311400553a0c3d5f"
|
||||
},
|
||||
{
|
||||
"path": "harness/experiments/diagram-readability-20260929/eight-answer-key.json",
|
||||
"bytes": 5337,
|
||||
"sha256": "8968fcc625e8584168ebb6b82f622307bdeb3db4c9c4fdbbc9fbdde3683a6efb"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-core/src/ports.rs",
|
||||
"bytes": 45413,
|
||||
"sha256": "5cac12eea70a54ebebbd6be77b63ce92e3195325c4bc7d27705c518686cbac80"
|
||||
}
|
||||
],
|
||||
"historical_archive_url": "http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/raw/commit/4fcb65c0d3ec7aabf2315bb3f08b64a7cdd2af99/harness/experiments/boundary-order-20260925/evidence/boundary-order-3e21c1bc.zip",
|
||||
"historical_archive_sha256": "bb6b896ff2401290869a904f7768ebb52b6f0ab36fada06badbe9abb301c37b8",
|
||||
"historical_producer": "3e21c1bca245944ae0ec7bb02aaa920f45f2cc30",
|
||||
"historical_geometry": "before only; candidate planner is paused and not used",
|
||||
"probe_source": {
|
||||
"path": "crates/oa-core/examples/diagram_readability_probe.rs",
|
||||
"sha256": "41e2d5b3f170138b87bf30c9b40971c221a62864558294db2be4e61b7b139989"
|
||||
},
|
||||
"initial_test_failure": {
|
||||
"source_commit": "2aac3e83532166dc45cd3519cc5d89b3e84d57f3",
|
||||
"log": ".local/probe-tests-failed24.log",
|
||||
"log_sha256": "897de362a2d001a83a6880138bc498a28b92602a350ac25405ee38fe81124cc8",
|
||||
"result": "1 passed; 4 failed admission; geometry generation not run",
|
||||
"correction": "Add 1 missing_system, 10 unallocated_leaf, and 25 empty_port_contract warnings from model records and validation/ports rules; no model or probe changes",
|
||||
"rationale": "warning-baseline-review.md"
|
||||
},
|
||||
"baseline_review": "Independent critic verified all 60 exact rows, no duplicates, original 24 rows unchanged, and original input hash preserved. Rerun pending."
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
Compiling oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `dev` profile [unoptimized] target(s) in 1.97s
|
||||
Running `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe.exe generate .local/issue38-probe-run01`
|
||||
@@ -1,2 +0,0 @@
|
||||
Finished `dev` profile [unoptimized] target(s) in 0.28s
|
||||
Running `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe.exe probe harness/experiments/diagram-readability-20260929/mixed-dispatch-original.json harness/experiments/diagram-readability-20260929/mixed-dispatch-expected-diagnostics.json 00000000-0000-0000-0000-0000000186a1 1982 375 1 .local/issue38-probe-query01.json`
|
||||
@@ -1,60 +0,0 @@
|
||||
{
|
||||
"source": "f754ad85d3674a709d10054e6fe23079f977c547",
|
||||
"recorded_utc": "2026-10-02T00:55:33.621109+00:00",
|
||||
"compiler": "rustc 1.98.1 (48a229cea 2026-09-01)",
|
||||
"target": "x86_64-pc-windows-gnullvm",
|
||||
"profile": "dev/unoptimized",
|
||||
"executable": {
|
||||
"bytes": 22633984,
|
||||
"sha256": "d94f86b2f4af594b27960cfa169fd681adb9b3a5eae2928dd72c541bc2db1c57"
|
||||
},
|
||||
"artifacts": {
|
||||
"mixed-dispatch-geometry.json": {
|
||||
"bytes": 122181,
|
||||
"sha256": "651707cba81ae78802cd21bd1aacc9b58a7b9239953f7395cef3b2fb8a5aa5ee"
|
||||
},
|
||||
"eight-card-representative-geometry.json": {
|
||||
"bytes": 206818,
|
||||
"sha256": "2c3e86e58f48272b818e764a339902599b502cb8b718f3ed8de8593651682f2c"
|
||||
},
|
||||
"query-mixed.json": {
|
||||
"bytes": 158526,
|
||||
"sha256": "09cffd48e67f619d5bb9edd8e684d0dba5289b303de4d2cf118b0ec670d8e9b7"
|
||||
},
|
||||
"fmt.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"tests.log": {
|
||||
"bytes": 837,
|
||||
"sha256": "b15549bf4400aa71fe7944bf53772dde1772aae74b89f3bce48f406cdbe0d3b9"
|
||||
},
|
||||
"generate.log": {
|
||||
"bytes": 292,
|
||||
"sha256": "3ca7a0a6b3b4181783bf7e15fea141ef5bc93fcb18e5697f87fec9372ede9085"
|
||||
},
|
||||
"query.log": {
|
||||
"bytes": 443,
|
||||
"sha256": "247d833a9438a0acd61f4a98a587475349033789fed9ed5d7d3eb22ff8a89949"
|
||||
},
|
||||
"initial-failed24.log": {
|
||||
"bytes": 54395,
|
||||
"sha256": "897de362a2d001a83a6880138bc498a28b92602a350ac25405ee38fe81124cc8"
|
||||
}
|
||||
},
|
||||
"results": {
|
||||
"fmt_exit": 0,
|
||||
"tests_exit": 0,
|
||||
"tests_passed": 5,
|
||||
"generate_exit": 0,
|
||||
"query_exit": 0,
|
||||
"historical_witness_reproduced": true
|
||||
},
|
||||
"commands": [
|
||||
"cargo fmt --all -- --check",
|
||||
"cargo test --locked -p oa-core --example diagram_readability_probe",
|
||||
"cargo run --locked -p oa-core --example diagram_readability_probe -- generate .local/issue38-probe-run01",
|
||||
"cargo run --locked -p oa-core --example diagram_readability_probe -- probe harness/experiments/diagram-readability-20260929/mixed-dispatch-original.json harness/experiments/diagram-readability-20260929/mixed-dispatch-expected-diagnostics.json 00000000-0000-0000-0000-0000000186a1 1982 375 1 .local/issue38-probe-query01.json"
|
||||
],
|
||||
"limits": "Headless full-scene geometry and conservation checks only; no native usability, selection, edit/history/save acceptance or production change."
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
Compiling oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `test` profile [unoptimized] target(s) in 2.39s
|
||||
Running unittests examples\diagram_readability_probe.rs (C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe-6772f474561e0ccd.exe)
|
||||
|
||||
running 5 tests
|
||||
test tests::analytical_query_controls_distinguish_edges_segments_and_labels ... ok
|
||||
test tests::complete_scene_preserves_semantics_sentinel_and_authored_route ... ok
|
||||
test tests::square_port_corner_is_occluded_even_outside_ten_unit_circle ... ok
|
||||
test tests::unexpected_diagnostics_and_invalid_source_fail_closed ... ok
|
||||
test tests::representative_preserves_every_original_record_and_view ... ok
|
||||
|
||||
test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.28s
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# Current-router full-scene evidence
|
||||
|
||||
Source `f754ad85d3674a709d10054e6fe23079f977c547` passes formatting, all five
|
||||
probe tests, fixture generation and the separate declared-point query on Windows
|
||||
gnullvm. [Receipt and raw logs](run-f754/receipt.json) bind the executable hash,
|
||||
compiler, commands and artifacts. The original one-pass/four-failure warning
|
||||
admission run remains preserved; [source-derived correction](warning-baseline-review.md)
|
||||
and independent record review establish the exact 60-warning fixture baseline.
|
||||
No model or production validator changed.
|
||||
|
||||
The current router reproduces the historical witness: two real exchanges
|
||||
`...01adb8` and `...01adb9` share a 78-unit run at x1982, y336..414. Query
|
||||
`(1982,375)` at zoom1 finds both at distance zero and no reported node, port,
|
||||
ordinary-label or association-label occluder. Both also retain distinct label
|
||||
and line samples elsewhere. This is point ambiguity, not global inaccessibility.
|
||||
|
||||
Independent read-only review verified all recorded input/source hashes, complete
|
||||
answer-key inventories and Project conservation. The mixed scene has ten nodes
|
||||
and fourteen routes; its authored feedback and sentinel view remain intact. The
|
||||
representative scene has eight nodes and twelve routes; removing its added view
|
||||
recovers the original Project exactly. JSON expansion of an authored f32 `.4`
|
||||
to `.4000000059604645` reflects serialization, not a changed model value.
|
||||
|
||||
The representative contains two unlabeled PortAllocations sharing x1065,
|
||||
y89.5..361, with a ChainInvolvement six world units away. At `(1065,200)` the two
|
||||
PortAllocations are coincident and the ChainInvolvement is at distance6. At
|
||||
`(1065,430)` the latter PortAllocation is at zero and ChainInvolvement at six;
|
||||
`(1071,430)` reverses those distances. The conservative alternate-access probe
|
||||
finds no single-candidate samples for either PortAllocation. Production chooses
|
||||
the nearest segment before selection/identity ties, so this result does not
|
||||
establish native inaccessibility. These are useful distance and tie controls.
|
||||
|
||||
The Technician service conversation's label center is 134.5 units horizontally
|
||||
displaced from its route anchor, providing a local label-association repair case.
|
||||
Native evaluation should first record unaided tracing, then deliberate selection
|
||||
with coincident and distance controls, label/bend repair, cancellation, exact
|
||||
Undo/Redo/save/reopen, and drawing a valid relationship in the populated scene.
|
||||
Inspector lookup does not count as unaided reading. No routing candidate or GUI
|
||||
workflow has been accepted from this headless evidence.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Independent preparatory review
|
||||
|
||||
Read-only review of the new Rust probe, fixed inputs/answer keys, experiment
|
||||
contract and production projection/picking code. No compiler, probe or GUI was
|
||||
run by the reviewer. No remaining source blocker was identified before execution.
|
||||
|
||||
The author addressed these consequential findings:
|
||||
|
||||
- Port-owner mapping adds five valid relationships to the representative view:
|
||||
its complete inventory is twelve, rather than seven. Kind, semantic endpoints,
|
||||
ports, projected endpoints and trace identity are checked independently.
|
||||
- Port occlusion follows the actual square half-width `max(10/zoom, 10)` world
|
||||
units, with a corner control; association-end label rectangles also precede
|
||||
ordinary line picking and are included.
|
||||
- Query candidates count semantic edges separately from their matching segments.
|
||||
Empty ordinary labels do not occlude a point merely because bounds remain.
|
||||
- Historical reproduction requires both declared real identities, zero distance,
|
||||
no occluder and the recorded common span. Declared source provenance requires
|
||||
actual build/fixture verification before a current-router claim.
|
||||
|
||||
Admission, warning baselines and current routing remain execution gates.
|
||||
Two flat scenes cannot establish nested/folded behavior; Traceability removes
|
||||
visual parents. Geometric samples do not establish native selection, readability
|
||||
or global inaccessibility. Read-only Project equality does not verify edit
|
||||
transactions, Undo/Redo or save/reopen. Drawing a new relation requires a separate
|
||||
declared post-change answer key and Project delta.
|
||||
|
||||
The next workflow should trace, deliberately select, repair one label or bend,
|
||||
then undo in the complete scene, with unique labels/unshared spans as controls.
|
||||
Creating a valid relation, refusal and cancellation are separate tasks. A chooser
|
||||
that prints correct endpoints cannot substitute for unaided diagram readability.
|
||||
@@ -1,65 +0,0 @@
|
||||
# Archived warning baseline correction
|
||||
|
||||
The parent compiled source `2aac3e83532166dc45cd3519cc5d89b3e84d57f3` and reported
|
||||
one test passed / four failed at strict admission. The original expected baseline
|
||||
contained 24 warnings. Geometry generation did not run. The failed log remains at
|
||||
`.local/probe-tests-failed24.log`; its SHA256 is recorded in `provenance.json` for later
|
||||
publication by the parent. This correction has not been compiled or executed by
|
||||
the research agent.
|
||||
|
||||
Independent source inspection establishes the following additional 36 warnings.
|
||||
An intermediate, unexecuted 35-warning correction covered system/allocation rules
|
||||
only; independent critique caught the additional 25 typed-port warnings before rerun.
|
||||
No diagnostic output was imported to construct them, and the original model bytes
|
||||
remain unchanged (SHA256 81d25af021cbad18af4262a220ba60372e51ca19083b7e80f2b19196baf05990).
|
||||
|
||||
* `crates/oa-core/src/validation.rs:253–264` warns when any element is SA and no
|
||||
element is a System. The archived model has 10 SA Functions and 25 SA Ports,
|
||||
with no System. Therefore exactly one `missing_system` warning belongs to
|
||||
project `00000000-0000-0000-0000-0000000186a0`, field `elements`, message
|
||||
`Identify the SA system of interest.`
|
||||
* `validation.rs:339–351` warns for each leaf work element with no effective
|
||||
performer. All ten Functions below have no Function child (their own parents
|
||||
are null; any children are Ports). All 14 relations are FunctionalExchanges;
|
||||
there are no Allocations, RoleAssignments, or RoleRealizations. The resolver
|
||||
at `validation.rs:2865–2893` consequently returns no performer for each.
|
||||
Each receives severity `Warning`, code `unallocated_leaf`, field `allocation`,
|
||||
and message `Allocate leaf '<name>' to a performer.` The warning helper at
|
||||
`validation.rs:45–53` retains the supplied element ID and severity.
|
||||
|
||||
| Element ID suffix (prefix `00000000-0000-0000-0000-000000`) | Exact name |
|
||||
| --- | --- |
|
||||
| 018704 | Sensor A |
|
||||
| 018706 | Sensor B |
|
||||
| 018708 | Ingest |
|
||||
| 01870a | Validate |
|
||||
| 01870c | Archive |
|
||||
| 01870e | Correlate |
|
||||
| 018710 | Plan |
|
||||
| 018712 | Dispatch |
|
||||
| 018714 | Actuator |
|
||||
| 018716 | Operator |
|
||||
|
||||
* `crates/oa-core/src/ports.rs:774–815` warns for an empty typed FunctionInput or
|
||||
FunctionOutput item list. All 25 archived Ports have these SA typed contracts:
|
||||
13 FunctionInputs with empty `incoming_items`, and 12 FunctionOutputs with empty
|
||||
`outgoing_items`. Their warning element is the exact Port identity, severity
|
||||
`Warning`, code `empty_port_contract`, field respectively `incoming_items` or
|
||||
`outgoing_items`, and message `This function port has no declared exchange items.`
|
||||
The expected JSON records each identity explicitly. `validation.rs:413` dispatches
|
||||
these elements to the port validator. No generic legacy or component contracts
|
||||
occur, so the separate legacy/orientation warning rules do not apply.
|
||||
|
||||
The complete model inventory is 35 elements (10 Functions and 25 Ports), 14 relations
|
||||
(all FunctionalExchange, with empty carried-item lists), two views, and no traces.
|
||||
There are no sequences, occurrences, states, capabilities, data objects, or other
|
||||
relation families to trigger their specific warning rules. The behavior-context,
|
||||
system, allocation, and typed-port rules exhaust the applicable warning families.
|
||||
|
||||
The existing 24 expected warning records remain intact. The corrected 60-record
|
||||
baseline remains exact: missing, extra, changed-field, changed-message, or error
|
||||
diagnostics still fail. These warnings describe the deliberately incomplete
|
||||
archived synthetic architecture; accepting them as a fixture baseline does not
|
||||
certify architectural completeness. No production rule, probe admission policy,
|
||||
model record, route, or test was weakened. The parent must rerun the tests before
|
||||
claiming successful admission or current-router geometry.
|
||||
@@ -1,6 +0,0 @@
|
||||
native-reading/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
*.json -text whitespace=cr-at-eol
|
||||
issue38-design-*.md -text whitespace=cr-at-eol
|
||||
launch-reading*.py -text whitespace=cr-at-eol
|
||||
label-candidates/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
first-exposure/** -text whitespace=-blank-at-eol,-blank-at-eof,cr-at-eol
|
||||
@@ -1,104 +0,0 @@
|
||||
# Full-scene reading and local editing experiment
|
||||
|
||||
This is evidence for [issue 38](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/38),
|
||||
not a production readability fix or full diagram acceptance. The complete
|
||||
eight-card mixed view is a documented reconstruction, not the user's recovered
|
||||
view. Its original semantic inventory and probe source are in the
|
||||
[September 29 experiment](../diagram-readability-20260929/README.md).
|
||||
|
||||
Native desktop source is `6e7c4ddaf0775198384a8c4882809ea8e14b2976`, executable
|
||||
SHA256 `d55ecad4b0f75c0c9c26625e5441bef9c9360890b65bc13236c6ebfaf03d631e`.
|
||||
Its unchanged routing/core source is the released `715036e` foundation. Geometry
|
||||
queries use probe source `f754ad85d3674a709d10054e6fe23079f977c547`, executable
|
||||
SHA256 `d94f86b2f4af594b27960cfa169fd681adb9b3a5eae2928dd72c541bc2db1c57`.
|
||||
Launch receipts record the exact runtime, system-only child PATH and copied inputs.
|
||||
|
||||
## Observations and conservation
|
||||
|
||||
[Initial reading](native-reading/review.md) records endpoint/path uncertainty.
|
||||
Opening simpler OA/SA views incidentally exposed answers, so it is not pristine
|
||||
blind accuracy evidence. [Assisted inspection](native-reading/assisted/review.md)
|
||||
identifies all three named relations and both distinct port mappings through the
|
||||
actual UI. The conversation label caused a wrong first stroke selection of an
|
||||
ordinary Allocation. Shared-stroke clicks retain the already selected mapping;
|
||||
with no selection they choose one stable mapping. There is no visible chooser or
|
||||
cycling. Both mappings remain reachable through Connections and learned segments;
|
||||
this is ambiguous discovery, not global inaccessibility.
|
||||
|
||||
[Manual editing](native-reading/manual/review.md) predeclares a conversation-label
|
||||
move, then exercises label Undo/Redo and bend add/move/remove with exact restoration.
|
||||
The first native chooser attempt displayed the requested filename but exported to
|
||||
`project.json`; it is preserved as a discrepancy. A second attempt using actual
|
||||
focused typing and Return exports the requested `manual-label.json` with identical
|
||||
bytes. This supports the input-method explanation without proving the first
|
||||
failure's exact cause. JSON export deliberately retains source save state.
|
||||
|
||||
[Independent full-model and geometry review](native-reading/manual/independent-oracle-review.md)
|
||||
confirms the sole stored delta: one label-only route record for `sa_contact`, with
|
||||
empty waypoints and no attachment overrides. All semantic records, ports, six
|
||||
diagrams' other data, 35 placements and original routes remain identical. All 12
|
||||
computed paths and 11 other computed labels are also identical. The displacement
|
||||
is consistent with the recorded mouse gesture and rounded Fit 52%; exact zoom
|
||||
was not independently captured. The review explicitly corrects a transcribed UUID
|
||||
while retaining the original declared record and named intent.
|
||||
|
||||
[Fresh native reopen](native-reading/reopen/review.md) verifies the label's
|
||||
persistence and selection in the complete saved view. Both desktop processes
|
||||
exit 0 with empty logs; pristine input and both exported JSON files retain their
|
||||
pinned bytes. Eight cards are visibly present, while exact relation conservation
|
||||
comes from the model/geometry oracle, not counting coincident strokes visually.
|
||||
Menu Escape cancellation was exercised; mid-drag cancellation remains unverified
|
||||
because the available native tool exposes atomic completed drags.
|
||||
|
||||
## Next experiment and rejection criteria
|
||||
|
||||
[Candidate comparison](issue38-design-candidates.md) evaluates ownership-aware
|
||||
automatic placement, selective unselected association cues and selection-only
|
||||
cues. The [fresh critic](issue38-design-critic.md) finds that the current candidate
|
||||
set has no collision-free placement in this witness; its initial report was an
|
||||
unexecuted double-precision reconstruction. The
|
||||
[restricted Rust confirmation](label-candidates/README.md) now passes all six
|
||||
probe tests, real CLI enumeration, strict example Clippy and byte/model checks.
|
||||
All 184 candidates are evaluated; all six best choices still cross the same
|
||||
foreign Allocation. The retained first test failure was a declared segment-index
|
||||
miscount corrected against the original geometry, with no other assertion changed.
|
||||
This rejects ownership tie-breaking within the fixed existing generator and best
|
||||
collision tuple for the declared nearest-box metric, rather than automatic
|
||||
placement generally. Manual repair intersects both
|
||||
own and foreign strokes and is not a fresh reading success or a validated distance
|
||||
metric. A short boundary-to-anchor cue remains an experiment with explicit noise,
|
||||
shared-anchor, export, cache and first-association rejection gates.
|
||||
|
||||
A separate [fresh first-exposure screenshot review](first-exposure/review.md),
|
||||
without opening-view cues or model lookup, assigns the conversation label to the
|
||||
foreign technician-to-repair Allocation and its arrowhead. Request/report reading
|
||||
remains uncertain. This is one agent's static reading of the actual complete
|
||||
baseline Fit screenshot, not a human study or native interaction acceptance.
|
||||
It corroborates the misassociation independently of the earlier cued reading.
|
||||
|
||||
No production routing or rendering change is accepted here. Direct new-exchange
|
||||
drawing, full shared-corridor readability, broad accessibility/DPI and complete
|
||||
OA/SA acceptance remain outstanding. Authoritative scope and ownership are in
|
||||
Gitea, rather than an additional local live-task ledger.
|
||||
|
||||
## Reproduce the bounded checks
|
||||
|
||||
The [inventory](evidence-files.json) pins the captured files before this README
|
||||
and attributes were authored. Scoped attributes preserve all native snapshot bytes.
|
||||
Copy `native-reading` into a fresh scratch directory before rerunning its Python
|
||||
oracles, which write reports; do not overwrite historical evidence. These helpers
|
||||
are verification glue, not application code. Run `check-manual-geometry.py` on
|
||||
the retained before/after geometry and inspect its precise assertions and limits.
|
||||
|
||||
With the identified probe source and Rust/toolchain environment, reproduce both
|
||||
geometry queries from the repository root, using fresh output filenames:
|
||||
|
||||
```powershell
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- probe harness/experiments/diagram-readability-20261001/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 600 450 1 BEFORE.json
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- probe harness/experiments/diagram-readability-20261001/native-reading/working/manual-label.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 600 450 1 AFTER.json
|
||||
```
|
||||
|
||||
The captured launchers contain original absolute paths; adapt them to a fresh
|
||||
copied working folder and the exact released binaries. Native reports give the
|
||||
actual pointer, keyboard, selection and chooser sequence. Tool/recording elapsed
|
||||
times are not measured human task times.
|
||||
@@ -1,23 +0,0 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json,subprocess,sys
|
||||
root=Path(subprocess.check_output(['git','rev-parse','--show-toplevel'],text=True).strip())
|
||||
packet=root/sys.argv[1]
|
||||
entries=json.loads((packet/'evidence-files.json').read_text(encoding='utf-8'))
|
||||
names=list(entries)
|
||||
prefix=packet.relative_to(root).as_posix()
|
||||
requests=[':'+prefix+'/'+name for name in names]
|
||||
assert all('\n' not in name for name in requests)
|
||||
stream=subprocess.check_output(['git','cat-file','--batch'],input=('\n'.join(requests)+'\n').encode('utf-8'),cwd=root)
|
||||
offset=0
|
||||
for name in names:
|
||||
end=stream.index(b'\n',offset)
|
||||
header=stream[offset:end].decode('ascii').split()
|
||||
assert len(header)==3 and header[1]=='blob',(name,header)
|
||||
size=int(header[2]);offset=end+1
|
||||
indexed=stream[offset:offset+size];offset+=size
|
||||
assert stream[offset:offset+1]==b'\n';offset+=1
|
||||
data=(packet/name).read_bytes()
|
||||
assert {'bytes':len(data),'sha256':hashlib.sha256(data).hexdigest()}==entries[name],name
|
||||
assert indexed==data,'Indexed snapshot bytes differ: '+name
|
||||
assert offset==len(stream)
|
||||
print(json.dumps({'status':'PASS','captured_files':len(names),'all_indexed_bytes_identical':True},indent=2))
|
||||
@@ -1,298 +0,0 @@
|
||||
{
|
||||
"issue38-design-candidates.md": {
|
||||
"bytes": 9149,
|
||||
"sha256": "9b2f69e2ccab90940bd293d707562745f77f34c2158d9d4c93811f86fc477e37"
|
||||
},
|
||||
"issue38-design-critic.md": {
|
||||
"bytes": 11440,
|
||||
"sha256": "83af5f48985b95f9e573896164e1a01621e2cf21fcfb865f3a53f4b6454e8271"
|
||||
},
|
||||
"launch-reading-reopen.py": {
|
||||
"bytes": 2160,
|
||||
"sha256": "da6292e5183560d75b1aa8dc61de9782bd6d1eb557d4ee141d5ad352f3b0bc74"
|
||||
},
|
||||
"launch-reading.py": {
|
||||
"bytes": 2199,
|
||||
"sha256": "e67c4da095e16d6302a1ea378ac1e60a2567311150b02a11604768e037dc5ed0"
|
||||
},
|
||||
"native-reading/check-manual-geometry.py": {
|
||||
"bytes": 2967,
|
||||
"sha256": "aaf75f040ecb7179787386a28ec279fa06b5975caefc49deb88fb94cd0a34915"
|
||||
},
|
||||
"native-reading/check-manual-label.py": {
|
||||
"bytes": 1412,
|
||||
"sha256": "4bae942d211cc033267024229f8c151d329b04a1ba094abcd6d9f65f4250820e"
|
||||
},
|
||||
"native-reading/finished.json": {
|
||||
"bytes": 886,
|
||||
"sha256": "20ce9c8623978a6d486f42db85a32bc65262b5a64dbf3bffdbd1ef032508631f"
|
||||
},
|
||||
"native-reading/fit-52.png": {
|
||||
"bytes": 151267,
|
||||
"sha256": "6ab503b18cc5425f49f20197cbcee47893cdb47e632506123d50241d8dda07df"
|
||||
},
|
||||
"native-reading/review.md": {
|
||||
"bytes": 6223,
|
||||
"sha256": "0f12f2b06278d9f82b088a5c459ce2aed6de6b1de6ffb6297558f51c1864c70d"
|
||||
},
|
||||
"native-reading/started.json": {
|
||||
"bytes": 742,
|
||||
"sha256": "3c8cab17424dc8b4ab178a6eaa3bc6a5e0e58a8122644b578750047c60fcd095"
|
||||
},
|
||||
"native-reading/stderr.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"native-reading/stdout.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"native-reading/zoom-62.png": {
|
||||
"bytes": 151470,
|
||||
"sha256": "67b8e0968fdcc2dbb0c25e1a2427b5952a770a000a2980678265027a83306d1a"
|
||||
},
|
||||
"native-reading/assisted/01-request-top.png": {
|
||||
"bytes": 154004,
|
||||
"sha256": "0bce2c90c1e27d140a5bbaa3bfae073e8b588c92b82a667dbef12c3b919899dc"
|
||||
},
|
||||
"native-reading/assisted/02-request-endpoints.png": {
|
||||
"bytes": 157675,
|
||||
"sha256": "a6776b0e4231fb752a1d0758f61b1f2cfae870664fd70fd9b11b358787c1154d"
|
||||
},
|
||||
"native-reading/assisted/03-report-top.png": {
|
||||
"bytes": 153822,
|
||||
"sha256": "5898fb753b78a073b789de2a149173785c2e2514ada27cfc4a9c53921e130f86"
|
||||
},
|
||||
"native-reading/assisted/04-report-endpoints.png": {
|
||||
"bytes": 157567,
|
||||
"sha256": "cb8f995af2032bed50bc6ac89bd40f70b9762948d9c792950a182f898f33a1b0"
|
||||
},
|
||||
"native-reading/assisted/05-conversation-top.png": {
|
||||
"bytes": 153696,
|
||||
"sha256": "fc2e08720a555de644deeaaa128d56397ab2ac4356f75a3c39cda642763bc0ee"
|
||||
},
|
||||
"native-reading/assisted/06-conversation-endpoints.png": {
|
||||
"bytes": 156742,
|
||||
"sha256": "f2867bad5dc2bcdd695369bb6a3c0a94602272e920aeaefc2615451e267c0173"
|
||||
},
|
||||
"native-reading/assisted/07-coincident-stroke-first.png": {
|
||||
"bytes": 152420,
|
||||
"sha256": "921b9c24a9058bc51e1faa9b38214507178c084d390550ceb9d77441685bcdeb"
|
||||
},
|
||||
"native-reading/assisted/08-allocation-connections.png": {
|
||||
"bytes": 142680,
|
||||
"sha256": "d0fb2b3e3152288cde7929ff0b96141595dda08e35a60fa9c8253967cde9827a"
|
||||
},
|
||||
"native-reading/assisted/09-actor-connections.png": {
|
||||
"bytes": 146153,
|
||||
"sha256": "f8df96c231764d8a862e9aaf12c522538667256a53300a797190052b60df08cd"
|
||||
},
|
||||
"native-reading/assisted/10-provider-two-mappings.png": {
|
||||
"bytes": 158635,
|
||||
"sha256": "3a58eaee6a1153551f66ed3e80400e49ecb2e930899c0caae371c77f70a5a689"
|
||||
},
|
||||
"native-reading/assisted/11-report-mapping-selected.png": {
|
||||
"bytes": 137880,
|
||||
"sha256": "1afece8094958e7b11d6cf4807c8f6d1dcd0656ba14972fad5a2507fc39b513c"
|
||||
},
|
||||
"native-reading/assisted/12-report-mapping-identity.png": {
|
||||
"bytes": 150985,
|
||||
"sha256": "e84477ea580cdf8b0c7b612d1bcf8d5582a8a3f187a66b107bee68deb4520d61"
|
||||
},
|
||||
"native-reading/assisted/13-provider-owner.png": {
|
||||
"bytes": 159447,
|
||||
"sha256": "7b823d7bbe9b9f4a7976b8b251b91899e8a2cba0c844b5bf3a502711825ae158"
|
||||
},
|
||||
"native-reading/assisted/14-request-mapping-selected.png": {
|
||||
"bytes": 137688,
|
||||
"sha256": "649c7c966efd7d5e4de960cb3ccfd04fc68eb409ae353e840f6389f554399b83"
|
||||
},
|
||||
"native-reading/assisted/15-request-mapping-identity.png": {
|
||||
"bytes": 150827,
|
||||
"sha256": "f97ac6d30244c16325174a552f31b2939a1dc9c5197c0336f93449e28bf25c07"
|
||||
},
|
||||
"native-reading/assisted/16-cleared-shared-stroke-request.png": {
|
||||
"bytes": 152484,
|
||||
"sha256": "8529c7961aaf4a1d73e5c6f069da9242f8877874ad5670f6ab29107878d91cdb"
|
||||
},
|
||||
"native-reading/assisted/17-lower-stroke-report.png": {
|
||||
"bytes": 152539,
|
||||
"sha256": "2723f8b2548d1d75789a2df7eab0d2759b42dbb6917da6efe141e93ac47102b7"
|
||||
},
|
||||
"native-reading/assisted/18-request-port-owner.png": {
|
||||
"bytes": 157447,
|
||||
"sha256": "3a1efcb8f0b1f77eed3964aad61e95bcdc72d636dcbe9256ede9c4c3c3ef0bda"
|
||||
},
|
||||
"native-reading/assisted/19-report-port-owner.png": {
|
||||
"bytes": 157881,
|
||||
"sha256": "be64ffa1f4ce15210e7f30f291c274fddfc2c56868961823da78e543695d4265"
|
||||
},
|
||||
"native-reading/assisted/20-client-port-owner.png": {
|
||||
"bytes": 158832,
|
||||
"sha256": "d83fc535129eb785ad3dc734a0967e0f844c626f3546f47e0d94ffa29a41ec0e"
|
||||
},
|
||||
"native-reading/assisted/21-request-output-owner.png": {
|
||||
"bytes": 156935,
|
||||
"sha256": "5a9d3bb9efdb8be8325681a687147597a36638aeb506f7abbfe9d8c0f5cd258b"
|
||||
},
|
||||
"native-reading/assisted/22-report-input-owner.png": {
|
||||
"bytes": 157438,
|
||||
"sha256": "3757eadc50f5420fb381de8a2aea2fcb3afc266560c0f0489adce00f9c583397"
|
||||
},
|
||||
"native-reading/assisted/review.md": {
|
||||
"bytes": 9198,
|
||||
"sha256": "ff9a9b2697f15466a12b8150dfd4cd01b24478e5177b9c8d076c6818bd15f7c2"
|
||||
},
|
||||
"native-reading/manual/01-baseline.png": {
|
||||
"bytes": 161792,
|
||||
"sha256": "0f0ad2653d8f579aa38b82775185b82a3433e7a701d7bbdd95dab4db8fb92b95"
|
||||
},
|
||||
"native-reading/manual/02-route-help.png": {
|
||||
"bytes": 242646,
|
||||
"sha256": "2be64e14da0a38c56773b8061fd6316644a9a22f8f73296adc8fde0b64979da0"
|
||||
},
|
||||
"native-reading/manual/03-selected-baseline.png": {
|
||||
"bytes": 152416,
|
||||
"sha256": "a2da288302d4cec09e0974bb91106aaa533b5828a8e06e48c59274b8be5cecea"
|
||||
},
|
||||
"native-reading/manual/04-label-moved.png": {
|
||||
"bytes": 149724,
|
||||
"sha256": "73e498a7dba460ea35f3cd75b67a9117ec921cb510e9c762721a250becb00855"
|
||||
},
|
||||
"native-reading/manual/05-label-undo.png": {
|
||||
"bytes": 148036,
|
||||
"sha256": "b63c1d2106b99ba8d0ccdb3e03dd0840745bcc8bb8f1360549c62f5c1e55d43e"
|
||||
},
|
||||
"native-reading/manual/06-label-redo.png": {
|
||||
"bytes": 148332,
|
||||
"sha256": "03470add72449ce69fc88cc508f2aea5730cbfaa01e6f31edc049b775cfc2b47"
|
||||
},
|
||||
"native-reading/manual/07-route-menu.png": {
|
||||
"bytes": 156885,
|
||||
"sha256": "03c2f87db01874fabe95f0fe3b3d7a293600d2028dd5c0a06b7f1761ea28bcc9"
|
||||
},
|
||||
"native-reading/manual/08-bend-added.png": {
|
||||
"bytes": 148594,
|
||||
"sha256": "b828af8ce0cf82fc6c98dc9088313b3cd50625333f7d165ffe8216e40c5a7d69"
|
||||
},
|
||||
"native-reading/manual/09-bend-moved.png": {
|
||||
"bytes": 149961,
|
||||
"sha256": "49259d46eb81fcbcf2fd5a5a29026756aa84ed94e5893079f5cf876c1fd48ea1"
|
||||
},
|
||||
"native-reading/manual/10-bend-menu.png": {
|
||||
"bytes": 160558,
|
||||
"sha256": "efe7cf4f4db22f3b31e04c6db24f087f38712633bd4c91ebbc53d98b04d4377e"
|
||||
},
|
||||
"native-reading/manual/11-bend-removed.png": {
|
||||
"bytes": 148487,
|
||||
"sha256": "37f49c1b738a8215ebcb8110057c7db6f8c5976b0b40a95fd9a943232c7abb23"
|
||||
},
|
||||
"native-reading/manual/12-remove-undone.png": {
|
||||
"bytes": 147422,
|
||||
"sha256": "f6f56811911f3a3286d59d886249c852c25511c3c1e9f3bdcd776058f546944f"
|
||||
},
|
||||
"native-reading/manual/13-move-undone.png": {
|
||||
"bytes": 147165,
|
||||
"sha256": "78fafe6aacfdf383427c2e5f9a9fd27adf54201b7bc7e7aff2993ffcdf5b3e82"
|
||||
},
|
||||
"native-reading/manual/14-route-restored-label-kept.png": {
|
||||
"bytes": 147092,
|
||||
"sha256": "7b8814dd0061f1b844379205615fe039c5fb7814f35b9d0c96490849a31b78ea"
|
||||
},
|
||||
"native-reading/manual/15-menu-cancelled.png": {
|
||||
"bytes": 146989,
|
||||
"sha256": "4dcbbe0bdefb4b4a18e5a0e0d1762be45b064764314c96d63947997aaea4c390"
|
||||
},
|
||||
"native-reading/manual/16-save-formats.png": {
|
||||
"bytes": 61644,
|
||||
"sha256": "29810a2cf9e097a7cdd7733b8fba0623d43ee3a1ed4dc94ef7fb0e98f1e11612"
|
||||
},
|
||||
"native-reading/manual/17-save-json-path.png": {
|
||||
"bytes": 58079,
|
||||
"sha256": "abc813aabe25def65e138e3e6b96de171f68ba10c2065fef9575f99b9e003b16"
|
||||
},
|
||||
"native-reading/manual/18-export-unexpected-path.png": {
|
||||
"bytes": 151214,
|
||||
"sha256": "86a877d8d0b2d8189425450e48ea65a6481d5694c6347260bb3c48308321c0b9"
|
||||
},
|
||||
"native-reading/manual/19-typed-filename.png": {
|
||||
"bytes": 60453,
|
||||
"sha256": "1139b1ae391a2d0c4b46cb7e43d6b769714f81b546b894bbc2298d61d0a1edd7"
|
||||
},
|
||||
"native-reading/manual/20-correct-export-path.png": {
|
||||
"bytes": 151746,
|
||||
"sha256": "d947e11040a3a4b01746632e4de2ce6107f876db78eacf29321f4cec516054e1"
|
||||
},
|
||||
"native-reading/manual/21-close-prompt.png": {
|
||||
"bytes": 141053,
|
||||
"sha256": "90a5a67be0089bf451a87c84c772141e83354f4b8d9a42e0a2704ea13680a010"
|
||||
},
|
||||
"native-reading/manual/full-diff.json": {
|
||||
"bytes": 569,
|
||||
"sha256": "a471a21fbc1cd7b214dece0274ff91456e643813b8376dd69bf5aed491dd8b7d"
|
||||
},
|
||||
"native-reading/manual/geometry-after.json": {
|
||||
"bytes": 361826,
|
||||
"sha256": "453b8bdbd1c347987c39437ecd532193cb51a787c5dc19125bcacb01e8661592"
|
||||
},
|
||||
"native-reading/manual/geometry-before.json": {
|
||||
"bytes": 360890,
|
||||
"sha256": "497605352c2a746ab1908324016b9bb8b1540e34433449c91135418e7d0e88d8"
|
||||
},
|
||||
"native-reading/manual/geometry-comparison.json": {
|
||||
"bytes": 2260,
|
||||
"sha256": "3cb6c06f2c8ad2ea8bc7c79088b6f77358c8efed899b7d0c09ba15667c6c6fd0"
|
||||
},
|
||||
"native-reading/manual/independent-oracle-review.md": {
|
||||
"bytes": 8656,
|
||||
"sha256": "9b5bd1ce279d711ec83b311d00ad241b3df12ab19318a69e62b8f524c96217dd"
|
||||
},
|
||||
"native-reading/manual/review.md": {
|
||||
"bytes": 10356,
|
||||
"sha256": "30040642465c70edac3febd94c3f0b84954e46e4b8b4a161b5d702845e27a7d4"
|
||||
},
|
||||
"native-reading/manual/second-export-check.json": {
|
||||
"bytes": 192,
|
||||
"sha256": "eadafec0102a9a79689d0667fc578cd0ef91e239673a9ed03eafa0c6f1f6891c"
|
||||
},
|
||||
"native-reading/reopen/01-fit.jpg": {
|
||||
"bytes": 150997,
|
||||
"sha256": "2e1cadb2e27b505183caef34e87d201920530442761dad02e9435dc8d538df5b"
|
||||
},
|
||||
"native-reading/reopen/02-selected.jpg": {
|
||||
"bytes": 153708,
|
||||
"sha256": "50faf5df191b404187a0c3f422ef7c99c6aa8284acbe3d07cf9efc983c410d75"
|
||||
},
|
||||
"native-reading/reopen/finished.json": {
|
||||
"bytes": 864,
|
||||
"sha256": "ec7fe5a4acc2dca7eb0ba2a7c16ecd83374ace32a5a0022bf912ba8000ff8e6a"
|
||||
},
|
||||
"native-reading/reopen/review.md": {
|
||||
"bytes": 3707,
|
||||
"sha256": "5cd02784205bc77cde4405e2f5cea7db4408b719ae3cfaa3ae26236fdbca1903"
|
||||
},
|
||||
"native-reading/reopen/started.json": {
|
||||
"bytes": 721,
|
||||
"sha256": "3cd876d30b1235302bdafa8b36cdc2af0beb0c95ed80842e7876eb28274935c4"
|
||||
},
|
||||
"native-reading/reopen/stderr.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"native-reading/reopen/stdout.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"native-reading/working/eight-card.json": {
|
||||
"bytes": 138661,
|
||||
"sha256": "9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8"
|
||||
},
|
||||
"native-reading/working/manual-label.json": {
|
||||
"bytes": 138933,
|
||||
"sha256": "39572f8ab176f7b8ac8933a308dcf7b127aa15e3d4f627ef604325a5275812f2"
|
||||
},
|
||||
"native-reading/working/project.json": {
|
||||
"bytes": 138933,
|
||||
"sha256": "39572f8ab176f7b8ac8933a308dcf7b127aa15e3d4f627ef604325a5275812f2"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"review.md": {
|
||||
"bytes": 6334,
|
||||
"sha256": "e3f083690868f6d4514de4baa8b6b5dd4930a34c8b4270df640bd4dbf1d532ab"
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
# First-exposure static screenshot reading
|
||||
|
||||
I inspected only `C:/ar-diagram-01a0d717/.local/native-reading/fit-52.png` using `view_image` with `detail: original`. The screenshot is 1442 by 932 pixels. It shows the native Arcadia Studio Architecture page, the view titled “Issue 38 representative eight-card mixed view”, and 52% zoom. I read the working agreement in AGENTS.md but did not inspect source code, model data, answer keys, other reports, comparison images, or external research. The interpretations below are my first readings, recorded before receiving any correctness feedback.
|
||||
|
||||
## Request field repair
|
||||
|
||||
My initial candidate is a directed relation from “Assess pressure alarm” to “Repair valve in the field”, but I cannot confidently establish the first endpoint from this view. Endpoint confidence is low. The label appears just above the horizontal stroke at about y = 611. That stroke runs left to a vertical near x = 430 and right to the closely spaced vertical strokes just left of the repair card. A small open green triangle at the repair card's upper left edge, near y = 591, appears to point toward the card. This suggests a directed arrival at the repair function, with moderate confidence in that local reading.
|
||||
|
||||
The difficult part is establishing which path actually belongs to the label. Following the left vertical upward brings me into the rectangular route above and around “Pressure coordination service”, while other strokes meet or cross near the right edge of “Assess pressure alarm”. Following the right vertical upward brings me toward “Assess an alarm procedure” and the line running toward the actor. I cannot tell reliably whether these are connected branches, crossings, or overlapping independent routes. “Assess an alarm procedure” is therefore a plausible alternative first endpoint; a route involving “Pressure coordination service” is also visually easy to infer. My initial assess-to-repair candidate partly uses the nearby card positions and the label's meaning. It is not a confidently traced endpoint pair.
|
||||
|
||||
## Report repair result
|
||||
|
||||
My initial candidate is a directed relation from “Repair valve in the field” to “Confirm safe pressure”. Endpoint confidence is low to moderate. The label appears above the horizontal stroke at about y = 646. That stroke runs between the repair card's lower left corner and a vertical near x = 521. Following that vertical downward brings me toward the horizontal stroke at y = 797 and an open green triangle pointing into the right edge of “Confirm safe pressure”. This supports the candidate direction toward confirmation.
|
||||
|
||||
However, the small open green triangle at the repair end of the labeled horizontal stroke appears to point left, away from the repair card, and is difficult to distinguish from the other open green card markers. I would tentatively read this as a directional relation, not confidently as an unoriented relation, but the marker convention is not self-explanatory in the screenshot. The same left vertical passes the small arrow at “Reset valve remotely” and intersects the horizontal near y = 568. A reader could therefore follow it to “Reset valve remotely”, or continue upward toward the assessment/service row. I cannot exclude those alternatives from geometry alone. The label meaning makes repair-to-confirmation seem reasonable, but it does not resolve the line ownership.
|
||||
|
||||
## Technician service conversation
|
||||
|
||||
My first reading is a directed relation from “Field technician” to “Repair valve in the field”. Confidence is high relative to the other two readings, and moderate to high overall. A vertical stroke leaves the bottom of the technician card near x = 933, turns left below the label, and then turns down into a small filled arrowhead at the top of the repair card near x = 883. That is a short, locally traceable path. I do not need the label meaning to infer the endpoint pair or downward direction.
|
||||
|
||||
The word “conversation” might suggest an unoriented or two-way relationship in ordinary language, but the visible route has a downward arrowhead. I would follow the visible marker rather than infer two-way semantics from the name. The technician card also has a separate square marker and route at its left edge; I would not assign that route to this label on my first reading.
|
||||
|
||||
## Reading effort and visual ambiguity
|
||||
|
||||
The complete eight-card layout is visible, but the card titles, type captions, and relation labels are very small at 52%. I can decipher the requested labels with concentrated inspection; they are not comfortable scanning text. Several card type captions are substantially harder to read than the card names. Thin grey strokes and very small arrowheads make a route's terminal direction harder to identify than the card structure.
|
||||
|
||||
The largest effort is tracking line identity across the middle of the view. The assessment/service row contains intersections and a route surrounding the service card. Near the repair card, several closely spaced verticals and horizontal turns compete for attention. Near the reset/confirmation cards, one apparent vertical can be followed toward several endpoints. I do not see an unmistakable junction-versus-crossing convention that resolves these alternatives in this image. The first two labels require repeated tracing and still leave uncertainty.
|
||||
|
||||
The blue and purple hollow squares at card boundaries, the green open triangles, and the small filled grey arrowheads appear to be different marker families. Without a visible legend, I cannot confidently separate semantic relation markers from ports or editing affordances. The screenshot says “0 selected”, which argues against treating every coloured boundary marker as a selection handle. The large pointer over Fit and its pale blue highlight look like cursor/UI markings rather than diagram semantics. The dotted canvas and tool buttons also look nonsemantic.
|
||||
|
||||
This is one agent's first-exposure reading of one static screenshot. It is not a human user study, a correctness determination against the underlying model, or acceptance evidence for native gestures, interaction, accessibility, or alternative zoom levels. It establishes only the interpretations and uncertainties observable to this evaluator in this archived Fit view.
|
||||
@@ -1,113 +0,0 @@
|
||||
# Issue 38: unselected label association candidates
|
||||
|
||||
Bounded design proposal, not an accepted implementation. No production changes,
|
||||
grouping, filtering, semantic collapse, or new selection behavior are proposed
|
||||
here. Parent owns synthesis after native evidence. The eight-card arrangement is
|
||||
a representative reconstruction, not the user's recovered view.
|
||||
|
||||
## Evidence and causal hypothesis
|
||||
|
||||
The independent [reading report](native-reading/review.md) recorded uncertainty
|
||||
about the unselected Technician service conversation label. The prior opening
|
||||
views exposed simpler answers, so this is not pristine blind endpoint accuracy.
|
||||
The [assisted report](native-reading/assisted/review.md) nevertheless records an
|
||||
actual wrong first stroke selection: ordinary Allocation to Repair instead of the
|
||||
conversation near its label. Both unlabeled port mappings were then individually
|
||||
reachable through Connections and learned canvas segments. Thus accessible
|
||||
identities do not settle the separate unselected-reading problem.
|
||||
|
||||
The [manual report](native-reading/manual/review.md) demonstrates label dragging
|
||||
and Undo/Redo, and temporary bend editing. Parent's
|
||||
[complete geometry comparison](native-reading/manual/geometry-comparison.json)
|
||||
reports only the target label metadata changed; the Project otherwise and all
|
||||
twelve computed paths remained exact. This demonstrates an existing repair
|
||||
mechanism, not that the repaired placement has passed fresh reading evaluation.
|
||||
|
||||
Inspected implementation:
|
||||
|
||||
- `crates/oa-core/src/routing.rs:612–660` settles paths before labels, incorporates
|
||||
association-end bounds, and retains other cached labels during previews.
|
||||
- `make_label` at 1363 preserves authored label fraction/offset exactly. Automatic
|
||||
candidates use at most 32 fractions and 8 offsets, with an 8192-comparison budget.
|
||||
The initial fraction is .5 and initial offset is (0,-18). It prefers the first
|
||||
zero-collision result and earlier candidates on equal scores.
|
||||
- `label_collisions` at 1483 scores a lexicographic tuple of node overlap count,
|
||||
earlier-label overlap count, and inflated-label/stroke crossing count. It has
|
||||
no ownership-association or foreign-path proximity term. A collision-free
|
||||
candidate is not necessarily associated perceptually with the correct route;
|
||||
bounded search also does not promise a collision-free candidate exists or wins.
|
||||
- `diagram.rs:1303–1370` renders active paths thicker and teal and colors active
|
||||
label text; ordinary labels get white backing. There is no label-to-anchor
|
||||
leader in this rendering block. Label geometry supplies both anchor and center.
|
||||
SVG labels are separately emitted near 2033, so any visual policy needs matching
|
||||
export consideration rather than a canvas-only silent discrepancy.
|
||||
|
||||
Baseline conversation anchor is (1162,274.5), center (1296.5,274.5), label width 233.
|
||||
Its center-to-anchor displacement is 134.5, but its nearest rectangle edge is only
|
||||
18 units from the own vertical route. Therefore **center displacement alone is a
|
||||
bad ambiguity metric**: it mostly measures half the long label's width. A candidate
|
||||
must consider the whole label box, own route, other routes, and visible scale.
|
||||
The independent native wrong association is stronger evidence than a distance
|
||||
threshold picked to fit this one image.
|
||||
|
||||
## Materially different candidates
|
||||
|
||||
| Candidate | Minimal experiment | Benefit and risk |
|
||||
| --- | --- | --- |
|
||||
| A. Automatic placement objective | Keep paths and authored labels exact; evaluate bounded automatic candidates for association with their own route in addition to existing overlap criteria. Initially reuse the current candidate set and budget. Compare an ownership-aware tie-break against a rule rejecting candidates through/closer to unrelated routes when a comparably clear own-route candidate exists. | No extra diagram ink; addresses the cause before selection. Risks: no good candidate in existing set, merely shifting ambiguity, instability under edits/UUID ordering, and conflating long-label width with displacement. Current flattened stroke inputs lack edge identity; ownership-aware scoring needs a deliberate small interface change, not a guessed nearest segment. |
|
||||
| B. Selective unselected association leader | Draw a nonsemantic leader from an ambiguous/displaced label boundary to its existing route anchor, only for labels meeting a declared geometric ambiguity condition. No arrowhead, no endpoint/node connection, no selectable semantic edge, and no stored route edit. | Preserves both authored and automatic label positions and shows association before selection. Risks: more crossings and noise, leaders mistaken for relationships, ambiguous landing on a shared run, screen-space flicker near thresholds, and canvas/SVG divergence. Limit condition must use box/route geometry and ambiguity, not center distance alone. A leader crossing another label/card is a failure, not an acceptable automatic side effect. |
|
||||
| C. Selection-only leader | Add the same association cue only while its label/edge is selected. | Lowest persistent noise; useful during inspection and label repair. It cannot fix the demonstrated first unselected association, because the user must already find the right label/edge. Treat as a complementary repair aid, not acceptance of #38's reading outcome. |
|
||||
|
||||
Candidate A must not weaken the node-overlap priority merely to improve a distance
|
||||
score. Test collision-preserving tie-break first; if it cannot change the failed
|
||||
placement, report that limitation before proposing different priorities or a
|
||||
larger candidate set. Candidate B must visibly differ from semantic paths beyond
|
||||
color (for example a restrained dotted connector without arrows), remain legible
|
||||
at Fit, and avoid port/arrowhead/junction-like endpoint marks. This is a design
|
||||
hypothesis requiring visual testing, not a prescribed final style.
|
||||
|
||||
## Evaluators before iteration
|
||||
|
||||
1. Freeze the full twelve-edge scene, source/build, camera and 52% Fit baseline.
|
||||
Use fresh readers or an unrelated-label variant to remove remembered answers.
|
||||
Before selection/Inspector, ask which path carries the conversation and which
|
||||
participant ports it joins. Record first chosen stroke, confidence, wrong
|
||||
turns, time and zoom/pan. Score text legibility separately from association.
|
||||
2. Repeat on Request/Report (positive controls), the long coincident port corridor,
|
||||
both shorter/longer labels, an intentionally displaced authored label, and a
|
||||
clear close label. A is expected not to move the authored control. B should
|
||||
reveal its association without decorating every ordinary close label.
|
||||
3. Measure per-label own/foreign rectangle-to-path clearance, occlusions, leader
|
||||
intersections if present, and Fit bounds. Do not substitute one weighted score
|
||||
for observed reading. At a shared anchor, a leader that still fails to reveal
|
||||
which distinct route continues is an explicit negative result.
|
||||
4. Require unchanged semantic objects/ports, placements, all authored metadata,
|
||||
and computed paths for pure label-placement/cue trials. Preserve Undo/Redo and
|
||||
save/reopen; derived cues add no history. Label dragging still commits once.
|
||||
Record automatic label settlement after commit rather than promising preview
|
||||
equality. Test UUID reorder and translation variants for order artifacts.
|
||||
5. Bound added work and compare actual scene/preview latency against baseline;
|
||||
avoid rescanning all route pairs every pointer move. Test Fit and working zoom,
|
||||
monochrome/low-color discrimination, and leader visibility against white
|
||||
backing. Count additional visible marks and ask whether users mistake a leader
|
||||
for a relation. Reject improvements requiring hidden edges or missing endpoints.
|
||||
|
||||
## Recommendation and revisit condition
|
||||
|
||||
First prototype **A as a bounded experiment**, because the automatic label is the
|
||||
failure source and manual relocation already demonstrates a geometry-preserving
|
||||
repair. Prefer evidence that a nearby candidate makes the correct association
|
||||
clear without extra strokes. This is not authorization to implement or change
|
||||
the router. Keep B as a materially different comparison, particularly for authored
|
||||
labels A must preserve. Revisit toward B if A cannot improve unselected reading
|
||||
without overlap, excessive search, unstable positions, or regressions elsewhere.
|
||||
Reject C as the sole fix even if assisted lookup becomes easier. Selection
|
||||
disambiguation remains a separate complementary outcome.
|
||||
|
||||
Primary comparison: Sirius explicitly documents an attachment link between an
|
||||
edge and its labels, including different behavior for selected edge versus
|
||||
selected label: [official diagram guide](https://eclipse.dev/sirius/doc/user/diagrams/Diagrams.html).
|
||||
Capella documents local label alignment and layout tools in its
|
||||
[official layout guide](https://github.com/eclipse-capella/capella/blob/master/doc/plugins/org.polarsys.capella.tipsandtricks.doc/html/Tips%20and%20tricks/8_Other%20layout%20facilities/8_Other%20layout%20facilities.mediawiki).
|
||||
These support association and local repair as established workflows; they do not
|
||||
establish that always-visible leaders reduce this scene's cognitive load.
|
||||
@@ -1,63 +0,0 @@
|
||||
# Independent critique: issue 38 label association
|
||||
|
||||
Local-only review at source `971b9721c34e574025144935291944c871ccca16`. Read-only source/geometry/native-report inspection; no compilation, native interaction, production edits, or Gitea actions. Root owns synthesis. The fixture is representative, not the original user view.
|
||||
|
||||
## Decision
|
||||
|
||||
Do not proceed directly from the candidate note to production A. Its proposed first experiment—an ownership-aware tie-break with the existing candidate set and collision priorities—has a concrete feasibility problem in this fixture. Existing candidate geometry cannot give the conversation label a better nearest-rectangle ownership score without changing another premise. First reproduce the bounded enumeration below in the established probe; if confirmed, record A-with-existing-candidates as rejected for this witness. A different candidate generator/objective requires an explicit new experiment, not quiet scope expansion.
|
||||
|
||||
B remains worth a tiny controlled visual comparison because its baseline anchor is on a unique segment and the required leader is short. It is not yet preferred as a solution: it leaves the misleading foreign stroke passing through the label, and a short dotted leader at Fit may be too weak to overcome that cue. C cannot meet the unselected-reading gate.
|
||||
|
||||
## Independently checked geometry
|
||||
|
||||
Sources: `crates/oa-core/src/routing.rs` (Rect, record_segments, route_diagram_impl, make_label, label_collisions); `crates/oa-desktop/src/diagram.rs` (scene cache and drawing); `.local/native-reading/manual/geometry-before.json`, `geometry-comparison.json`; initial/assisted/manual reports and archived `fit-52.png`.
|
||||
|
||||
The conversation is `63009b5f-539e-5914-b630-ec6b7fefb4d5`. Use geometry identity: an earlier native transcription in the assisted report has a different final UUID group. That reporting error does not change the visual evidence.
|
||||
|
||||
- Conversation baseline box: x=1180..1413, y=262.5..286.5; own vertical path x=1162, y=89.5..316.5. Own box/path distance is 18.
|
||||
- Ordinary allocation has a vertical path x=1312.5, y=179..325. It **passes through the conversation box**. Foreign distance is zero. This is stronger than merely being nearby, and the old stroke-collision scorer already detects it.
|
||||
- Manual box after drag: x=1086.845..1319.845, y=204.278..228.278. It intersects BOTH the own vertical stroke and the same foreign allocation. Thus both nearest-box distances become zero. Manual repair proves geometry-preserving editing, but its reported apparent improvement neither validates a nearest-box score nor proves fresh reading success. The foreign stroke now reaches near the label's right edge instead of near its center; box distance discards precisely that distinction.
|
||||
- The source uses a width estimate of seven world units per character plus sixteen, while native text is separately rendered at font size 13. Bounds measure backing/hit geometry, not exact glyph contours. Never present their clearance as a measured human perception threshold.
|
||||
|
||||
### Read-only existing-candidate enumeration
|
||||
|
||||
A JavaScript arithmetic reconstruction over the saved geometry enumerated the exact fraction/offset construction (double precision, no production execution): fractions .5, each path segment midpoint, .05 through .95, ordered by distance from .5 then numeric fraction and deduplicated; 23 fractions times eight offsets = 184 candidates. All eight projected cards have no visual parent, so obstacle rectangles are full card bounds inflated by 12. The 12 routes produce 37 distinct undirected segment geometries after the existing exact-segment deduplication. Earlier labels for the conversation are empty; there are no association end labels in this fixture.
|
||||
|
||||
Checked all candidates, intentionally without budget truncation to give A the strongest possible feasibility case. Candidate/node overlap and inflated-by-three candidate/stroke intersection follow the source's strict orthogonal intersection inequalities; nearest segment/box distances are independently calculated.
|
||||
|
||||
Result: no candidate has zero node overlaps and zero stroke intersections. The minimum for node-clear candidates is one intersected stroke. Exactly these six candidates achieve it:
|
||||
|
||||
| Fraction | Offset | Center y | Own distance | Foreign distance |
|
||||
| --- | --- | ---: | ---: | ---: |
|
||||
| .5 | (134.5, 0) | 274.5 | 18 | 0 |
|
||||
| .45 | (134.5, 0) | 294.8 | 18 | 0 |
|
||||
| .55 | (134.5, 0) | 254.2 | 18 | 0 |
|
||||
| .6 | (134.5, 0) | 233.9 | 18 | 0 |
|
||||
| .65 | (134.5, 0) | 213.6 | 18 | 0 |
|
||||
| segment midpoint, about .676108 | (134.5, 0) | 203 | 18 | 0 |
|
||||
|
||||
Every center x is 1296.5. Every candidate intersects that ordinary allocation. An ownership tie-break can at most change height among these candidates, not resolve the bad owner overlap. Since this enumeration uses double arithmetic and a source reconstruction, it is a falsifiable feasibility finding to confirm with the Rust probe, not a claim of production test execution. The candidates are well away from geometric boundary conditions, making rounding an unlikely reversal.
|
||||
|
||||
## What defeats each proposal
|
||||
|
||||
**A: candidate feasibility and objective semantics.** Collision preservation is not just a protection against regression here: it restricts the winning set to six still-misleading placements. Adding a weighted distance or trying more of the same search cannot fix the absent placement. If a later experiment permits a label backing to cover its own stroke while avoiding foreign strokes, that is a different objective and should be stated and compared explicitly. Do not quietly weaken node/other-label priorities. A global optimization framework, spatial index, or generalized routing API is unnecessary before demonstrating one useful local rule.
|
||||
|
||||
**A: ownership is not one ID per existing Segment.** `record_segments` merges exactly coincident segments and keeps a count; partially overlapping strokes remain separate geometries. Assigning a single owner to the merged segment will falsely treat a shared own/foreign stroke as unique. For the experiment, retain edge-tagged polylines separately from existing route-cost Segment storage; compute ambiguity across distinct semantic edges. Avoid changing routing segment accounting to support label scoring. A long shared run can have own distance zero and foreign distance zero everywhere, so proximity cannot prove identity.
|
||||
|
||||
**A: removing zero-score early exit changes actual cost.** Current scoring exits as soon as (0,0,0) appears, and early-prunes worse candidates. A tie-break that requires finding the best association among all zero-collision candidates loses that exit. If distance work is not charged against the comparison budget, keeping the old 8192 variable does not keep the computational contract. Charge or separately cap all candidate/segment work and expose exhaustion in the experimental report. Never accept an incompletely scored candidate as a better one.
|
||||
|
||||
**A: stable UUID order is repeatability, not invariance.** Both path order and earlier-label precedence depend on UUID. Relabeling UUIDs and recomputing the whole diagram changes paths as well as labels, confounding a label-only evaluation. Run two controls: frozen-path scoring with permuted label order/IDs, and a complete reroute with consistent UUID remapping. Reordering array storage with identical IDs should remain exact. Count all automatically moved labels, even if their stored metadata and paths are unchanged.
|
||||
|
||||
**B: this fixture has a useful but weak testable leader.** Shortest boundary-to-anchor segment is (1180,274.5) to (1162,274.5), length 18, about 9.3 screen pixels at the measured Fit. It reaches a unique own vertical segment without an intervening card/path. That makes it a favorable local leader witness. However, the foreign allocation still passes through the label farther right. A few dots at Fit may disappear or read as another short relationship/branch. A center-to-anchor leader would unnecessarily cross the label backing and should not be used. Any cue must be drawn in an ordering that survives white label backing and later edge strokes; the current loop interleaves individual paths and labels rather than painting all text in one last pass. Match export.
|
||||
|
||||
**B: shared landing and zoom threshold.** A leader to a shared run names no unique route; endpoint markers would add misleading semantics. Reject such a case rather than counting an attachment as success. A threshold based on screen pixels may flicker on zoom and accidentally make camera changes require rescoring all geometry; derive geometry with the scene, keep camera policy simple, and test threshold boundaries. Blanket unselected leaders for every label are not justified.
|
||||
|
||||
**C: circular first-use dependency.** The correct label is already selectable and selection already reveals the full path. Another selected cue may help editing but does not fix the first unselected inference. Accept only as an independently scoped editing aid.
|
||||
|
||||
## Smallest falsifiable next experiments
|
||||
|
||||
1. **Confirm feasibility before implementation.** Extend the existing experimental probe/report, not production routing, to list the current candidates, full old collision tuple, owner-tagged intersection list, own/foreign distance, and actual comparisons consumed. Reproduce the six-candidate result, including baseline. Reject A's existing-set collision-preserving form if it cannot produce a candidate whose owning path is perceptually distinguishable from the allocation. Pure distance improvement is insufficient; a changed height alone is not an automatic pass.
|
||||
2. **Native visual comparison with fixed geometry.** Compare baseline against B's one short boundary leader, plus the already-saved manual label state as an empirical control. The manual state is not a promised good answer. Use a fresh reader or unrelated-label variant; directly open the mixed view; no Inspector before answers. Ask for first chosen path and participant ports, then Request/Report and the two port mappings. Observe both ordinary Fit and working zoom. Record first wrong turn, confidence, tracing time, extra pan/zoom, and whether any cue is mistaken for a semantic relation. Reject a candidate if the original wrong association persists, another relation worsens, cue meaning needs an explanation before it can be used, or complete-scene simultaneous reading is lost. One reader can falsify a design; one success cannot establish broad usability.
|
||||
3. **Only if geometry changes become promising, test settlement and latency.** Preserve full Project and all paths; quantify every derived-label movement after an unrelated edit/Undo, label drag/commit, bend drag/commit, and save/reopen. Cache ordinary hover/selection work: the existing scene cache already avoids rerouting unchanged geometry; route previews freeze other labels, while node/port changes and commit can rebuild. Measure the actual affected rebuild/gesture paths, not a hypothetical reroute on every hover. Compare repeated baseline/candidate timings on both this scene and an existing dense control; reject missed interaction budgets or visible label jumping introduced by the candidate. Establish the latency ceiling from the project's existing performance work, not a newly invented threshold.
|
||||
|
||||
These experiments should precede any release claim. Passing a conversation-label test leaves the other full-view route-branch/shared-corridor reading failures open.
|
||||
@@ -1,21 +0,0 @@
|
||||
# Label candidate confirmation: initial scope
|
||||
|
||||
Bounded issue 38 experiment, delegated by root. Modify only `crates/oa-core/examples/diagram_readability_probe.rs`; parent is sole compiler and integration owner. No production router/renderer changes, GUI, Gitea, commit, or build/test execution by this agent.
|
||||
|
||||
Add read-only `label-candidates INPUT EXPECTED_DIAGNOSTICS DIAGRAM_UUID EDGE_UUID NEW_OUTPUT_JSON` with create-new output. Reconstruct current candidate geometry and full f32 collision scores for flat nodes and simple label context; reject unsupported nested nodes, association-end labels, and earlier nonempty labels. Preserve Project and source bytes. Enumerate an unbudgeted exhaustive superset; do not claim to simulate the production comparison budget or winner.
|
||||
|
||||
Expected falsification witness: 23 fractions times 8 offsets; no node-clear/stroke-clear candidate; six optimum (0,0,1) candidates, all intersecting ordinary `sa_repair_allocation`, own/foreign box clearances 18/0. One fixture test will assert the independently declared expected table with f32 tolerance. Parent will compile and verify actual output before treating findings as confirmed.
|
||||
|
||||
## Implementation ready for parent verification
|
||||
|
||||
Implemented the bounded command in the existing probe and added one representative-fixture falsification test. The report includes each candidate's f32 geometry, full collision tuple, owner-preserving semantic stroke intersections, and uninflated own/foreign box clearances. The command rejects unsupported geometry/label contexts and uses existing diagnostics admission and create-new writing. Existing generate/probe commands and tests remain in place.
|
||||
|
||||
Static review and `git diff --check` completed; no build, formatter, or tests run by this agent. Parent should format the touched Rust file, run the probe's six tests, and execute the new command against the immutable representative input with release1 diagnostics. Expected values are predeclared in the new test; actual Rust output is not yet confirmed.
|
||||
|
||||
Suggested invocation arguments (after the parent's normal build setup):
|
||||
|
||||
```text
|
||||
label-candidates .local/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 63009b5f-539e-5914-b630-ec6b7fefb4d5 NEW_OUTPUT_JSON
|
||||
```
|
||||
|
||||
Source reviewed by author; parent independently owns code/result review. This is not a fresh second critic's implementation review.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Restricted existing-candidate feasibility confirmation
|
||||
|
||||
Executed source `70cf350d23ed3a47ca843754220e4f45fa51aa47`: formatting, all six
|
||||
probe tests, real CLI enumeration and strict example Clippy pass on Windows
|
||||
gnullvm. The first five-pass/one-fail run at `05b1b1d` is retained. Its declared
|
||||
segment index was independently reconciled against the original saved geometry;
|
||||
the entire successor code change is `[2]` to `[1]` in that expectation. No scoring,
|
||||
other expected values or production implementation changed.
|
||||
|
||||
Actual f32 enumeration confirms 184 candidates, zero node-clear/stroke-clear
|
||||
choices, and six best `(0,0,1)` choices. Every best box is 18 world units from its
|
||||
own route and intersects the same foreign ordinary allocation at segment index1.
|
||||
The parent reconciled the complete CLI Project/input bytes and all six owner-tagged
|
||||
winner rows. A second CLI call against its already-existing output fails with
|
||||
AlreadyExists; both input and prior output remain byte-exact. Raw output, gate
|
||||
logs, initial failure, author reconciliation, independent source/arithmetic review,
|
||||
source manifest and parent result remain in this packet.
|
||||
|
||||
This rejects candidate A only as specified: ownership-aware tie-breaking inside
|
||||
the existing generator, preserving the best collision tuple and fixed routes,
|
||||
cannot repair the declared nearest-box ownership metric for this reconstructed
|
||||
view. It does not reject new candidate generators/objectives or automatic layout
|
||||
generally, and does not establish that alternate heights cannot aid perception.
|
||||
The exhaustive probe omits production budgets/early exit; no chooser latency or
|
||||
winner simulation is claimed. Restrictions include flat nodes, an automatic
|
||||
unsuspended nonempty target label, no association-end/earlier nonempty labels,
|
||||
and finite orthogonal paths. The representative view is not recovered user source.
|
||||
Native reading of candidate B remains separate.
|
||||
|
||||
The parent's first direct guard harness omitted the DLL search path and failed
|
||||
its expected-error assertion before capturing a result. A separately retained
|
||||
repeat returns Windows `0xc0000135` with empty streams; this is a startup failure,
|
||||
not a create-new guard pass. The corrected harness explicitly supplies the pinned
|
||||
libunwind directory and system PATH. That actual repeat reaches AlreadyExists.
|
||||
|
||||
From this checkout with Rust configured:
|
||||
|
||||
```powershell
|
||||
cargo fmt --all -- --check
|
||||
cargo test --locked -p oa-core --example diagram_readability_probe
|
||||
cargo clippy --locked -p oa-core --example diagram_readability_probe -- -D warnings
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- label-candidates harness/experiments/diagram-readability-20261001/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 63009b5f-539e-5914-b630-ec6b7fefb4d5 NEW_OUTPUT_JSON
|
||||
```
|
||||
|
||||
Choose a nonexistent output path. The collector retains historical absolute paths
|
||||
and performs a deliberate existing-output guard attempt; it is provenance, not a
|
||||
portable replay script. Inventory hashes cover all subpacket files except the
|
||||
inventory itself. Runtime provenance requires the external manifest/source gates;
|
||||
the JSON's embedded experiment description alone is not a build identity.
|
||||
@@ -1,109 +0,0 @@
|
||||
from pathlib import Path
|
||||
import hashlib, json, os, shutil, subprocess
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
source = '70cf350d23ed3a47ca843754220e4f45fa51aa47'
|
||||
assert subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip()==source
|
||||
sha = lambda b: hashlib.sha256(b).hexdigest()
|
||||
load = lambda p: json.loads(p.read_text(encoding='utf-8'))
|
||||
inp = root/'.local/native-reading/working/eight-card.json'
|
||||
output = root/'.local/label-candidates-corrected.json'
|
||||
raw_input = inp.read_bytes(); raw_output = output.read_bytes(); value = load(output)
|
||||
assert sha(raw_input)=='9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8'
|
||||
assert value['project']==json.loads(raw_input) and value['original_input_utf8']==raw_input.decode('utf-8')
|
||||
assert value['project_conserved'] and value['input_bytes_conserved']
|
||||
assert (value['fraction_count'],value['offset_count'],value['candidate_count'],value['distinct_stroke_count'])==(23,8,184,37)
|
||||
assert value['zero_node_zero_stroke_count']==0 and value['best_collision_tuple']==[0,0,1]
|
||||
winners=[value['candidates'][i] for i in value['best_candidate_indices']]
|
||||
assert len(winners)==6
|
||||
for candidate in winners:
|
||||
assert candidate['own_clearance']==18 and candidate['foreign_clearance']==0
|
||||
assert candidate['own_intersections']==[]
|
||||
assert candidate['foreign_intersections']==[{'edge':'725f2e1b-aa2c-5615-9b1f-28da178168fa','relation_alias':'sa_repair_allocation','segments':[1]}]
|
||||
exe=Path('C:/Users/User/Documents/Git/ARCADIA-Studio/.local/target-gnullvm/debug/examples/diagram_readability_probe.exe')
|
||||
command=[str(exe),'label-candidates',str(inp),str(root/'examples/release1/expected-diagnostics.json'),
|
||||
'00000000-0038-4000-8000-000000000001','63009b5f-539e-5914-b630-ec6b7fefb4d5',str(output)]
|
||||
runtime=Path('C:/ar-compact-01a0d717/.local/package39/bin/libunwind.dll')
|
||||
assert sha(runtime.read_bytes())=='f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4'
|
||||
env=os.environ.copy(); system=os.environ['SystemRoot']
|
||||
env['PATH']=str(runtime.parent)+';'+str(Path(system)/'System32')+';'+system
|
||||
guard=subprocess.run(command,cwd=root,env=env,capture_output=True)
|
||||
assert guard.returncode!=0 and b'AlreadyExists' in guard.stderr
|
||||
assert inp.read_bytes()==raw_input and output.read_bytes()==raw_output
|
||||
packet=root/'harness/experiments/diagram-readability-20261001/label-candidates'
|
||||
packet.mkdir(exist_ok=False)
|
||||
for name in ['label-candidates-first-failed.log','label-candidates-corrected-format.log',
|
||||
'label-candidates-corrected-tests.log','label-candidates-corrected-cli.log',
|
||||
'label-candidates-corrected-clippy.log','label-candidates-corrected.json',
|
||||
'label-candidates-summary.md','label-candidates-independent-review.md',
|
||||
'label-candidates-guard-without-runtime-repeated.json']:
|
||||
shutil.copyfile(root/'.local'/name,packet/name)
|
||||
shutil.copyfile(Path(__file__),packet/'collect-label-candidates.py')
|
||||
source_files=['crates/oa-core/examples/diagram_readability_probe.rs','crates/oa-core/src/routing.rs',
|
||||
'examples/release1/model.json','examples/release1/expected-diagnostics.json',
|
||||
'harness/experiments/diagram-readability-20260929/eight-card-view.json','Cargo.lock']
|
||||
manifest={'source':source,'input_sha256':sha(raw_input),'output_sha256':sha(raw_output),
|
||||
'binary_sha256':sha(exe.read_bytes()),'runtime_sha256':sha(runtime.read_bytes()),'files':{}}
|
||||
for name in source_files:
|
||||
b=subprocess.check_output(['git','show',source+':'+name],cwd=root)
|
||||
manifest['files'][name]={'bytes':len(b),'sha256':sha(b)}
|
||||
(packet/'source-manifest.json').write_text(json.dumps(manifest,indent=2)+'\n',encoding='utf-8')
|
||||
receipt={'status':'PASS','source':source,'candidate_count':184,'best_candidates':winners,
|
||||
'input_bytes_and_complete_project_conserved':True,'existing_output_guard':{
|
||||
'command':command,'exit_code':guard.returncode,'stdout':guard.stdout.decode('utf-8'),
|
||||
'stderr':guard.stderr.decode('utf-8'),'path':env['PATH'],'runtime_sha256':sha(runtime.read_bytes()),'input_unchanged':True,'output_unchanged':True}}
|
||||
(packet/'result.json').write_text(json.dumps(receipt,indent=2)+'\n',encoding='utf-8')
|
||||
(packet/'README.md').write_text('''# Restricted existing-candidate feasibility confirmation
|
||||
|
||||
Executed source `70cf350d23ed3a47ca843754220e4f45fa51aa47`: formatting, all six
|
||||
probe tests, real CLI enumeration and strict example Clippy pass on Windows
|
||||
gnullvm. The first five-pass/one-fail run at `05b1b1d` is retained. Its declared
|
||||
segment index was independently reconciled against the original saved geometry;
|
||||
the entire successor code change is `[2]` to `[1]` in that expectation. No scoring,
|
||||
other expected values or production implementation changed.
|
||||
|
||||
Actual f32 enumeration confirms 184 candidates, zero node-clear/stroke-clear
|
||||
choices, and six best `(0,0,1)` choices. Every best box is 18 world units from its
|
||||
own route and intersects the same foreign ordinary allocation at segment index1.
|
||||
The parent reconciled the complete CLI Project/input bytes and all six owner-tagged
|
||||
winner rows. A second CLI call against its already-existing output fails with
|
||||
AlreadyExists; both input and prior output remain byte-exact. Raw output, gate
|
||||
logs, initial failure, author reconciliation, independent source/arithmetic review,
|
||||
source manifest and parent result remain in this packet.
|
||||
|
||||
This rejects candidate A only as specified: ownership-aware tie-breaking inside
|
||||
the existing generator, preserving the best collision tuple and fixed routes,
|
||||
cannot repair the declared nearest-box ownership metric for this reconstructed
|
||||
view. It does not reject new candidate generators/objectives or automatic layout
|
||||
generally, and does not establish that alternate heights cannot aid perception.
|
||||
The exhaustive probe omits production budgets/early exit; no chooser latency or
|
||||
winner simulation is claimed. Restrictions include flat nodes, an automatic
|
||||
unsuspended nonempty target label, no association-end/earlier nonempty labels,
|
||||
and finite orthogonal paths. The representative view is not recovered user source.
|
||||
Native reading of candidate B remains separate.
|
||||
|
||||
The parent's first direct guard harness omitted the DLL search path and failed
|
||||
its expected-error assertion before capturing a result. A separately retained
|
||||
repeat returns Windows `0xc0000135` with empty streams; this is a startup failure,
|
||||
not a create-new guard pass. The corrected harness explicitly supplies the pinned
|
||||
libunwind directory and system PATH. That actual repeat reaches AlreadyExists.
|
||||
|
||||
From this checkout with Rust configured:
|
||||
|
||||
```powershell
|
||||
cargo fmt --all -- --check
|
||||
cargo test --locked -p oa-core --example diagram_readability_probe
|
||||
cargo clippy --locked -p oa-core --example diagram_readability_probe -- -D warnings
|
||||
cargo run --locked -p oa-core --example diagram_readability_probe -- label-candidates harness/experiments/diagram-readability-20261001/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 63009b5f-539e-5914-b630-ec6b7fefb4d5 NEW_OUTPUT_JSON
|
||||
```
|
||||
|
||||
Choose a nonexistent output path. The collector retains historical absolute paths
|
||||
and performs a deliberate existing-output guard attempt; it is provenance, not a
|
||||
portable replay script. Inventory hashes cover all subpacket files except the
|
||||
inventory itself. Runtime provenance requires the external manifest/source gates;
|
||||
the JSON's embedded experiment description alone is not a build identity.
|
||||
''',encoding='utf-8')
|
||||
inventory={p.relative_to(packet).as_posix():{'bytes':p.stat().st_size,'sha256':sha(p.read_bytes())}
|
||||
for p in packet.rglob('*') if p.is_file()}
|
||||
(packet/'evidence-files.json').write_text(json.dumps(inventory,indent=2)+'\n',encoding='utf-8')
|
||||
print(json.dumps({'status':'PASS','captured_files':len(inventory),'source':source,'output_sha256':sha(raw_output)},indent=2))
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"collect-label-candidates.py": {
|
||||
"bytes": 7879,
|
||||
"sha256": "60530ad52007e2cc3b64b376784c902fcf1592a2263cf92357bd999f1e5dd746"
|
||||
},
|
||||
"label-candidates-corrected-cli.log": {
|
||||
"bytes": 476,
|
||||
"sha256": "a0b823c42c4e4bd82cf369c3dcae78505fa926c5859747836245c7b6f56000b2"
|
||||
},
|
||||
"label-candidates-corrected-clippy.log": {
|
||||
"bytes": 131,
|
||||
"sha256": "be3db997064a64f0decf6e32a939325d880930b52570cb1e38e71937ee71ed70"
|
||||
},
|
||||
"label-candidates-corrected-format.log": {
|
||||
"bytes": 0,
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"label-candidates-corrected-tests.log": {
|
||||
"bytes": 923,
|
||||
"sha256": "e992552c7a5ebc47978a8d076fe36025bde7eb96680176b71077fbd13a2e3ab9"
|
||||
},
|
||||
"label-candidates-corrected.json": {
|
||||
"bytes": 546617,
|
||||
"sha256": "3cc6a058fd7b16e1082b0aa38fa322147c129612fa3d27d30e54f7f75e63470b"
|
||||
},
|
||||
"label-candidates-first-failed.log": {
|
||||
"bytes": 1543,
|
||||
"sha256": "75e4759570bf1acc0d0b4eebaa6409d25d068d0877ff9700f7080f6569b92842"
|
||||
},
|
||||
"label-candidates-guard-without-runtime-repeated.json": {
|
||||
"bytes": 90,
|
||||
"sha256": "86e177b1b1018f67cb3554456e8981d664a134528cedbe80fd36a3e6f2030717"
|
||||
},
|
||||
"label-candidates-independent-review.md": {
|
||||
"bytes": 6763,
|
||||
"sha256": "5c5b81a13577b94de6abb18afecede2354103a7d4e1e12def84f6ead4068950b"
|
||||
},
|
||||
"label-candidates-summary.md": {
|
||||
"bytes": 4097,
|
||||
"sha256": "c28c4ea7e90f0abb9898f228234523e30236e8975ae7851dee88aeb37a53dcbc"
|
||||
},
|
||||
"README.md": {
|
||||
"bytes": 3304,
|
||||
"sha256": "fa6a397d948651be55cce7a5d9eefff653ceb1b4f6411863b3d8c3b45a9eea65"
|
||||
},
|
||||
"result.json": {
|
||||
"bytes": 6398,
|
||||
"sha256": "7d86a5ba5d1ef94d9c2703949d230ed6ae91c17b5f5c5a831538a1a24d6d44fe"
|
||||
},
|
||||
"source-manifest.json": {
|
||||
"bytes": 1419,
|
||||
"sha256": "da54db7e47c7b1bd0ace2fb2a86565ac4b6bcde4f65ad1e7f4cca8c4596ac6c1"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
Compiling oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `dev` profile [unoptimized] target(s) in 1.75s
|
||||
Running `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe.exe label-candidates .local/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 63009b5f-539e-5914-b630-ec6b7fefb4d5 .local/label-candidates-corrected.json`
|
||||
@@ -1,2 +0,0 @@
|
||||
Checking oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `dev` profile [unoptimized] target(s) in 17.18s
|
||||
@@ -1,14 +0,0 @@
|
||||
Compiling oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `test` profile [unoptimized] target(s) in 33.45s
|
||||
Running unittests examples\diagram_readability_probe.rs (C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe-6772f474561e0ccd.exe)
|
||||
|
||||
running 6 tests
|
||||
test tests::analytical_query_controls_distinguish_edges_segments_and_labels ... ok
|
||||
test tests::complete_scene_preserves_semantics_sentinel_and_authored_route ... ok
|
||||
test tests::square_port_corner_is_occluded_even_outside_ten_unit_circle ... ok
|
||||
test tests::unexpected_diagnostics_and_invalid_source_fail_closed ... ok
|
||||
test tests::conversation_existing_candidates_cannot_avoid_foreign_allocation ... ok
|
||||
test tests::representative_preserves_every_original_record_and_view ... ok
|
||||
|
||||
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.20s
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
Compiling oa-core v0.2.0 (C:\ar-diagram-01a0d717\crates\oa-core)
|
||||
Finished `test` profile [unoptimized] target(s) in 1m 26s
|
||||
Running unittests examples\diagram_readability_probe.rs (C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\examples\diagram_readability_probe-6772f474561e0ccd.exe)
|
||||
|
||||
running 6 tests
|
||||
test tests::analytical_query_controls_distinguish_edges_segments_and_labels ... ok
|
||||
test tests::complete_scene_preserves_semantics_sentinel_and_authored_route ... ok
|
||||
test tests::square_port_corner_is_occluded_even_outside_ten_unit_circle ... ok
|
||||
test tests::conversation_existing_candidates_cannot_avoid_foreign_allocation ... FAILED
|
||||
test tests::unexpected_diagnostics_and_invalid_source_fail_closed ... ok
|
||||
test tests::representative_preserves_every_original_record_and_view ... ok
|
||||
|
||||
failures:
|
||||
|
||||
---- tests::conversation_existing_candidates_cannot_avoid_foreign_allocation stdout ----
|
||||
|
||||
thread 'tests::conversation_existing_candidates_cannot_avoid_foreign_allocation' (7848) panicked at crates\oa-core\examples\diagram_readability_probe.rs:731:13:
|
||||
assertion `left == right` failed
|
||||
left: Array [Number(1)]
|
||||
right: Array [Number(2)]
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
||||
|
||||
failures:
|
||||
tests::conversation_existing_candidates_cannot_avoid_foreign_allocation
|
||||
|
||||
test result: FAILED. 5 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.72s
|
||||
|
||||
error: test failed, to rerun pass `-p oa-core --example diagram_readability_probe`
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"returncode": 3221225781,
|
||||
"hex": "0xc0000135",
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
# Independent review: restricted label candidate enumeration
|
||||
|
||||
No material source or conceptual defect found in the bounded enumeration. The helper is suitable to test the predeclared geometric feasibility claim. Corrected Rust execution remains a separate parent gate; no passing result is inferred from the earlier five-pass/one-fail run. This review does not accept a production label algorithm or general usability improvement.
|
||||
|
||||
## Exact scope
|
||||
|
||||
Read applicable AGENTS.md, design critic, original production routing implementation, added helper/CLI/test, initial failure and the one-line correction. Source addition: `05b1b1d804c4cd47d9c8ff464644e365d8ede5b2`; corrected assertion commit: `70cf350d23ed3a47ca843754220e4f45fa51aa47`. Current working tree was clean during review.
|
||||
|
||||
Working-file SHA256: `crates/oa-core/examples/diagram_readability_probe.rs` = `cbc6713a4974c77b1c8b44f12cb9e0a2271096bbbdbc883aae0c5ba9703ba483`; `crates/oa-core/src/routing.rs` = `b377fe80cece3892d64f62ba5e1578d8974eeefc2a317620f343a86f2f257fbd`.
|
||||
|
||||
Probe exact SHA256: `cbc6713a4974c77b1c8b44f12cb9e0a2271096bbbdbc883aae0c5ba9703ba483`.
|
||||
|
||||
No compiler, GUI, Gitea, commit or production edit. Read-only Python arithmetic independently reconstructed candidate geometry over previously captured baseline paths. This report is the only new artifact.
|
||||
|
||||
## Production correspondence
|
||||
|
||||
`LabelProbeRect` matches production rectangle construction, inflation, strict overlap and strict segment-intersection inequalities including EPSILON 0.001. Under the required exact orthogonality, its interval-separation/hypot clearance is the segment-to-uninflated-box distance, not a perceptual or glyph distance.
|
||||
|
||||
The flat-node guard makes all production traversable-ancestor sets empty, so full node rectangles inflated by 12 reproduce edge_obstacles. No association-end labels and no earlier nonempty ordinary labels imply the production prior-label collision component is exactly zero. Authored target labels and suspended custom routes are rejected. Unknown diagram/edge, empty label, too-short path, nonfinite or nonorthogonal paths and changed label dimensions are rejected rather than silently approximated.
|
||||
|
||||
Fraction generation matches production f32 length accumulation, segment midpoints, 1/20 increments, sorting by distance from 0.5 then numeric order, exact deduplication and truncation at 32. Eight offsets and label width/height reconstruction match. Anchor interpolation calls the actual production point_along_polyline helper. Final candidate bounds use the same f32 expression order.
|
||||
|
||||
Distinct nonzero strokes are deduplicated only by exact undirected endpoint equality, matching record_segments. Production label collision score counts each stored segment once and does not multiply by its multiplicity. The probe does the same; it separately walks original edge-tagged segment windows to retain every semantic owner and zero-based segment index. It therefore does not collapse coincident foreign ownership into the target's identity. Partially overlapping segments stay distinct in both paths.
|
||||
|
||||
The helper intentionally computes full tuples without the 8192 budget, early pruning or early successful exit. It enumerates the complete generator set, a superset of candidates actually examined by the production chooser. This is appropriate for proving absence within that set; it does not reproduce the actual chooser's work count, budget exhaustion, winner or latency. The report states that boundary.
|
||||
|
||||
## Independent witness reconciliation
|
||||
|
||||
Independent read-only arithmetic over the original geometry-before.json, with explicit f32 rounding of candidate/interpolation operations, reproduces 23 fractions, 184 candidates, 37 distinct strokes, minimum tuple (0,0,1), and precisely the declared six best fractions: 0.5, approximately 0.45/0.55/0.6/0.65/0.67610836. All use offset (134.5,0), center x1296.5 and the predeclared center y values within f32 tolerance. Their boxes remain 18 units from the own path and intersect the foreign allocation. This is independent arithmetic confirmation, not Rust test execution.
|
||||
|
||||
The first failed Rust log is preserved with SHA256 `75e4759570bf1acc0d0b4eebaa6409d25d068d0877ff9700f7080f6569b92842`. Its failed assertion was declared segment [2] versus actual [1]. The original captured allocation points are (1312.5,161), (1312.5,179), (1312.5,325), (1216,325), (1216,343). The offending vertical is therefore windows(2) index 1; index 2 is horizontal. Independent geometry supports correcting only [2] to [1]. Git confirms that is the entire successor change. The failed run stopped in the first winner row, so it does not establish successful completion of all six rows.
|
||||
|
||||
## Preservation and limits
|
||||
|
||||
The CLI uses existing exact-diagnostics admission, rejects model errors or changed warning sets, reads input bytes, retains original UTF-8 text in output, compares input bytes again after analysis, and writes through create_new. Existing outputs or output equal to input fail without replacement. Project is immutable to the helper and explicitly compared to its clone. These are read-only/single-writer experiment checks, not a filesystem lock or atomic cross-process promise. Create-new output can remain partial on a later write failure; failed attempts should stay identifiable.
|
||||
|
||||
The new test checks independently declared full-model preservation, candidate/stroke counts, absence of a zero-node/zero-stroke option, exact optimum tuple, all six expected best placements, ownership/alias/segment and clearance values. Unsupported-context rejection and create-new behavior are not newly exercised by this test. Source inspection supports them; do not turn this into a generic nested/association/earlier-label scorer without separate work.
|
||||
|
||||
The defensible conclusion after corrected execution is narrow: on these fixed representative paths, no existing generator candidate can improve the declared own-versus-foreign nearest-box relationship while preserving the best collision tuple. All six best candidates still intersect the same allocation. This does not prove every change in height is perceptually useless, all automatic placement strategies are impossible, a different candidate generator is unnecessary, or that the manual control/B cue improves fresh reading. Those require separately declared metrics and native evidence. The representative view remains a reconstruction, not recovered user source.
|
||||
|
||||
No material finding requires production changes. Before recording A's restricted metric formulation as rejected, retain the corrected Rust result/output, complete input/source identity and this explicit scope. Production budgets/performance and B native acceptance remain outside this review.
|
||||
@@ -1,39 +0,0 @@
|
||||
# Label candidate confirmation: initial scope
|
||||
|
||||
Bounded issue 38 experiment, delegated by root. Modify only `crates/oa-core/examples/diagram_readability_probe.rs`; parent is sole compiler and integration owner. No production router/renderer changes, GUI, Gitea, commit, or build/test execution by this agent.
|
||||
|
||||
Add read-only `label-candidates INPUT EXPECTED_DIAGNOSTICS DIAGRAM_UUID EDGE_UUID NEW_OUTPUT_JSON` with create-new output. Reconstruct current candidate geometry and full f32 collision scores for flat nodes and simple label context; reject unsupported nested nodes, association-end labels, and earlier nonempty labels. Preserve Project and source bytes. Enumerate an unbudgeted exhaustive superset; do not claim to simulate the production comparison budget or winner.
|
||||
|
||||
Expected falsification witness: 23 fractions times 8 offsets; no node-clear/stroke-clear candidate; six optimum (0,0,1) candidates, all intersecting ordinary `sa_repair_allocation`, own/foreign box clearances 18/0. One fixture test will assert the independently declared expected table with f32 tolerance. Parent will compile and verify actual output before treating findings as confirmed.
|
||||
|
||||
## Implementation ready for parent verification
|
||||
|
||||
Implemented the bounded command in the existing probe and added one representative-fixture falsification test. The report includes each candidate's f32 geometry, full collision tuple, owner-preserving semantic stroke intersections, and uninflated own/foreign box clearances. The command rejects unsupported geometry/label contexts and uses existing diagnostics admission and create-new writing. Existing generate/probe commands and tests remain in place.
|
||||
|
||||
Static review and `git diff --check` completed; no build, formatter, or tests run by this agent. Parent should format the touched Rust file, run the probe's six tests, and execute the new command against the immutable representative input with release1 diagnostics. Expected values are predeclared in the new test; actual Rust output is not yet confirmed.
|
||||
|
||||
Suggested invocation arguments (after the parent's normal build setup):
|
||||
|
||||
```text
|
||||
label-candidates .local/native-reading/working/eight-card.json examples/release1/expected-diagnostics.json 00000000-0038-4000-8000-000000000001 63009b5f-539e-5914-b630-ec6b7fefb4d5 NEW_OUTPUT_JSON
|
||||
```
|
||||
|
||||
Source reviewed by author; parent independently owns code/result review. This is not a fresh second critic's implementation review.
|
||||
|
||||
## First Rust run: declared segment-index transcription correction
|
||||
|
||||
Parent's first six-test run at frozen source `05b1b1d804c4cd47d9c8ff464644e365d8ede5b2` failed: five tests passed and the new fixture test stopped at its first-row segment-index assertion (actual `[1]`, declared `[2]`). Preserve `.local/label-candidates-tests.log` as failure evidence. Counts, optimum tuple, and first-row geometry/ownership assertions had passed before that point; the complete six-row finding remains pending the corrected run.
|
||||
|
||||
Independently reopened the original saved baseline `.local/native-reading/manual/geometry-before.json`, not the new Rust output. Ordinary allocation `725f2e1b-aa2c-5615-9b1f-28da178168fa` has these consecutive points:
|
||||
|
||||
```text
|
||||
0: (1312.5,161)
|
||||
1: (1312.5,179)
|
||||
2: (1312.5,325)
|
||||
3: (1216,325)
|
||||
4: (1216,343)
|
||||
```
|
||||
|
||||
Thus the vertical segment at x1312.5, y179..325 is zero-based window index **1**; index 2 is the horizontal segment at y325. The probe reports `edge.points.windows(2).enumerate()` indices, with no segment merging in its semantic owner lists. Production `record_segments` deduplication affects the independent collision tuple only, not these semantic indices. The candidate baseline box y262.5..286.5 intersects index 1 and cannot intersect horizontal index 2 even after its 3-unit inflation.
|
||||
|
||||
The `[2]` assertion was my declared index miscount, contradicted by the pre-existing geometry; it was not evidence of changed routing. Corrected only `[2]` to `[1]` in that assertion. No other expected value, tolerance, geometry rule, or assumption changed. No compile, test execution, GUI, commit, or Gitea action by this agent.
|
||||
@@ -1,278 +0,0 @@
|
||||
{
|
||||
"status": "PASS",
|
||||
"source": "70cf350d23ed3a47ca843754220e4f45fa51aa47",
|
||||
"candidate_count": 184,
|
||||
"best_candidates": [
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 274.5
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 262.5
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 274.5
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.5,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
},
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 294.79998779296875
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 282.79998779296875
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 294.79998779296875
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.44999998807907104,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
},
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 254.1999969482422
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 242.1999969482422
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 254.1999969482422
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.550000011920929,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
},
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 233.89999389648438
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 221.89999389648438
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 233.89999389648438
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.6000000238418579,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
},
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 213.60000610351562
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 201.60000610351562
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 213.60000610351562
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.6499999761581421,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
},
|
||||
{
|
||||
"anchor": {
|
||||
"x": 1162.0,
|
||||
"y": 203.0
|
||||
},
|
||||
"bounds": {
|
||||
"position": {
|
||||
"x": 1180.0,
|
||||
"y": 191.0
|
||||
},
|
||||
"size": {
|
||||
"height": 24.0,
|
||||
"width": 233.0
|
||||
}
|
||||
},
|
||||
"center": {
|
||||
"x": 1296.5,
|
||||
"y": 203.0
|
||||
},
|
||||
"collision_tuple": [
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"foreign_clearance": 0.0,
|
||||
"foreign_intersections": [
|
||||
{
|
||||
"edge": "725f2e1b-aa2c-5615-9b1f-28da178168fa",
|
||||
"relation_alias": "sa_repair_allocation",
|
||||
"segments": [
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"fraction": 0.6761083602905273,
|
||||
"offset": {
|
||||
"x": 134.5,
|
||||
"y": 0.0
|
||||
},
|
||||
"own_clearance": 18.0,
|
||||
"own_intersections": []
|
||||
}
|
||||
],
|
||||
"input_bytes_and_complete_project_conserved": true,
|
||||
"existing_output_guard": {
|
||||
"command": [
|
||||
"C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\.local\\target-gnullvm\\debug\\examples\\diagram_readability_probe.exe",
|
||||
"label-candidates",
|
||||
"C:\\ar-diagram-01a0d717\\.local\\native-reading\\working\\eight-card.json",
|
||||
"C:\\ar-diagram-01a0d717\\examples\\release1\\expected-diagnostics.json",
|
||||
"00000000-0038-4000-8000-000000000001",
|
||||
"63009b5f-539e-5914-b630-ec6b7fefb4d5",
|
||||
"C:\\ar-diagram-01a0d717\\.local\\label-candidates-corrected.json"
|
||||
],
|
||||
"exit_code": 1,
|
||||
"stdout": "",
|
||||
"stderr": "Error: Os { code: 80, kind: AlreadyExists, message: \"The file exists.\" }\n",
|
||||
"path": "C:\\ar-compact-01a0d717\\.local\\package39\\bin;C:\\Windows\\System32;C:\\Windows",
|
||||
"runtime_sha256": "f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4",
|
||||
"input_unchanged": true,
|
||||
"output_unchanged": true
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"source": "70cf350d23ed3a47ca843754220e4f45fa51aa47",
|
||||
"input_sha256": "9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8",
|
||||
"output_sha256": "3cc6a058fd7b16e1082b0aa38fa322147c129612fa3d27d30e54f7f75e63470b",
|
||||
"binary_sha256": "9e07a8cf703c1c3247d2b6f9bc63468fd4ad902f49f0a13b290104177db5230a",
|
||||
"runtime_sha256": "f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4",
|
||||
"files": {
|
||||
"crates/oa-core/examples/diagram_readability_probe.rs": {
|
||||
"bytes": 36267,
|
||||
"sha256": "cbc6713a4974c77b1c8b44f12cb9e0a2271096bbbdbc883aae0c5ba9703ba483"
|
||||
},
|
||||
"crates/oa-core/src/routing.rs": {
|
||||
"bytes": 53958,
|
||||
"sha256": "b377fe80cece3892d64f62ba5e1578d8974eeefc2a317620f343a86f2f257fbd"
|
||||
},
|
||||
"examples/release1/model.json": {
|
||||
"bytes": 134520,
|
||||
"sha256": "ef0ef4006c3e09d5db6e1b621256b3f7d6642f3a7b09cc34607cfbcca830c727"
|
||||
},
|
||||
"examples/release1/expected-diagnostics.json": {
|
||||
"bytes": 288,
|
||||
"sha256": "3700393d76b940cfc076bf52861bd7b1f43370f8eabce3594531bd0bf1fc851e"
|
||||
},
|
||||
"harness/experiments/diagram-readability-20260929/eight-card-view.json": {
|
||||
"bytes": 3641,
|
||||
"sha256": "f851e7e96fc6f5b1edb328b94eb991aa8e94b14cc1bcd07b2c42d32310c4527b"
|
||||
},
|
||||
"Cargo.lock": {
|
||||
"bytes": 119855,
|
||||
"sha256": "2aa80d113c5112b31c0767b874845d60f555e4e8ae7eb3ecd0b4b91954b55378"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
from pathlib import Path
|
||||
import datetime,hashlib,json,os,subprocess
|
||||
root=Path('C:/ar-diagram-01a0d717');reading=root/'.local/native-reading'
|
||||
run=reading/'reopen';run.mkdir(exist_ok=False)
|
||||
work=reading/'working'
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
baseline={p.name:sha(p) for p in work.glob('*.json')}
|
||||
assert baseline['manual-label.json']==baseline['project.json']=='39572f8ab176f7b8ac8933a308dcf7b127aa15e3d4f627ef604325a5275812f2'
|
||||
assert baseline['eight-card.json']=='9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8'
|
||||
bundle=Path('C:/ar-compact-01a0d717/.local/package39/extracted/ArcadiaStudio-0.2.0-preview.compact-help.20261001-x86_64-pc-windows-gnullvm')
|
||||
exe=bundle/'arcadia-studio.exe'
|
||||
assert sha(exe)=='d55ecad4b0f75c0c9c26625e5441bef9c9360890b65bc13236c6ebfaf03d631e'
|
||||
env=os.environ.copy();system=os.environ['SystemRoot'];env['PATH']=str(Path(system)/'System32')+';'+system
|
||||
for k in list(env):
|
||||
if k.startswith(('CARGO_','RUST','LLVM','WGPU','ARCADIA_')):del env[k]
|
||||
receipt={'source':'6e7c4ddaf0775198384a8c4882809ea8e14b2976','start':datetime.datetime.now(datetime.timezone.utc).isoformat(),'binary_sha256':sha(exe),'runtime_sha256':sha(bundle/'libunwind.dll'),'input_files':baseline,'cwd':str(work),'path':env['PATH']}
|
||||
with (run/'stdout.log').open('xb') as out,(run/'stderr.log').open('xb') as err:
|
||||
child=subprocess.Popen([str(exe)],cwd=work,env=env,stdout=out,stderr=err,creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
receipt['pid']=child.pid;(run/'started.json').write_text(json.dumps(receipt,indent=2)+'\n',encoding='utf-8');print(json.dumps(receipt,indent=2),flush=True)
|
||||
code=child.wait()
|
||||
receipt.update({'exit_code':code,'finished':datetime.datetime.now(datetime.timezone.utc).isoformat(),'stdout_bytes':(run/'stdout.log').stat().st_size,'stderr_bytes':(run/'stderr.log').stat().st_size,'inputs_unchanged':{p.name:sha(p) for p in work.glob('*.json')}==baseline})
|
||||
(run/'finished.json').write_text(json.dumps(receipt,indent=2)+'\n',encoding='utf-8');print(json.dumps(receipt,indent=2),flush=True)
|
||||
assert code==0 and receipt['stdout_bytes']==receipt['stderr_bytes']==0 and receipt['inputs_unchanged']
|
||||
@@ -1,23 +0,0 @@
|
||||
from pathlib import Path
|
||||
import datetime,hashlib,json,os,shutil,subprocess
|
||||
root=Path('C:/ar-diagram-01a0d717')
|
||||
run=root/'.local/native-reading';run.mkdir(exist_ok=False)
|
||||
work=run/'working';work.mkdir()
|
||||
fixture=root/'.local/issue38-probe-run01/eight-card-representative.json'
|
||||
shutil.copyfile(fixture,work/'eight-card.json')
|
||||
baseline=hashlib.sha256(fixture.read_bytes()).hexdigest()
|
||||
bundle=Path('C:/ar-compact-01a0d717/.local/package39/extracted/ArcadiaStudio-0.2.0-preview.compact-help.20261001-x86_64-pc-windows-gnullvm')
|
||||
exe=bundle/'arcadia-studio.exe'
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
assert sha(exe)=='d55ecad4b0f75c0c9c26625e5441bef9c9360890b65bc13236c6ebfaf03d631e'
|
||||
env=os.environ.copy();system=os.environ['SystemRoot'];env['PATH']=str(Path(system)/'System32')+';'+system
|
||||
for k in list(env):
|
||||
if k.startswith(('CARGO_','RUST','LLVM','WGPU','ARCADIA_')):del env[k]
|
||||
receipt={'source':'6e7c4ddaf0775198384a8c4882809ea8e14b2976','routing_core_source':'715036e132677dd2bc2fb37ed316d93dc9987aec','fixture_probe_source':'f754ad85d3674a709d10054e6fe23079f977c547','start':datetime.datetime.now(datetime.timezone.utc).isoformat(),'binary_sha256':sha(exe),'runtime_sha256':sha(bundle/'libunwind.dll'),'fixture_sha256':baseline,'fixture':str(work/'eight-card.json'),'cwd':str(work),'path':env['PATH']}
|
||||
with (run/'stdout.log').open('xb') as out,(run/'stderr.log').open('xb') as err:
|
||||
child=subprocess.Popen([str(exe)],cwd=work,env=env,stdout=out,stderr=err,creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
receipt['pid']=child.pid;(run/'started.json').write_text(json.dumps(receipt,indent=2)+'\n',encoding='utf-8');print(json.dumps(receipt,indent=2),flush=True)
|
||||
code=child.wait()
|
||||
receipt.update({'exit_code':code,'finished':datetime.datetime.now(datetime.timezone.utc).isoformat(),'stdout_bytes':(run/'stdout.log').stat().st_size,'stderr_bytes':(run/'stderr.log').stat().st_size,'fixture_unchanged':sha(work/'eight-card.json')==baseline})
|
||||
(run/'finished.json').write_text(json.dumps(receipt,indent=2)+'\n',encoding='utf-8');print(json.dumps(receipt,indent=2),flush=True)
|
||||
assert code==0 and receipt['stdout_bytes']==receipt['stderr_bytes']==0 and receipt['fixture_unchanged']
|
||||
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 154 KiB |
@@ -1,58 +0,0 @@
|
||||
# Issue 38 assisted native diagram review
|
||||
|
||||
Continuation of ../review.md on the same app/fixture. Parent-supplied executable and fixture identities and the opening-view cue caveat in that report remain applicable. The earlier phase is not pristine blind accuracy evidence. This assisted phase intentionally uses visible Inspector and Connections data; no source, JSON, geometry, answer key or semantic oracle was read.
|
||||
|
||||
Normal launch window, complete representative mixed view, Traceability projection, Fit 52% throughout. Approximately 220.7 seconds from first assisted observation to final Escape, including observation, UI navigation, and progress messages; recording the report excluded. No pan/zoom, model edit, Apply changes, Save, filtering, hiding, projection change, placement, route edit, label edit, port attachment edit, or property edit occurred. Selection and Inspector scroll only. App left open, 0 selected, Fit52%; navigator expanded naturally while following ports.
|
||||
|
||||
## Relations selected by visible labels
|
||||
|
||||
All three requested label clicks succeeded immediately. Inspector titles and stable aliases established relation kind and identity. Scrolling the Inspector exposed port endpoint fields and UUIDs. UUIDs below are manual transcriptions of visible fields, with screenshots as evidence.
|
||||
|
||||
| Relation | Kind / alias / UUID | Semantic endpoints and visible owners |
|
||||
| --- | --- | --- |
|
||||
| Request field repair | Functional exchange; sa_repair_request; 93474111-f23e-56c1-b61b-b7c2396b91bd | Source Assess pressure alarm, @sa_assess, via Request field repair output @sa_repair_request_out; target Repair valve in the field via Request field repair input @sa_repair_request_in |
|
||||
| Report repair result | Functional exchange; sa_repair_report; 684eadc3-e670-5779-a60f-bbc9a5bfb062 | Source Repair valve in the field via Report repair result output @sa_repair_report_out; target Confirm safe pressure @sa_confirm via Report repair result input @sa_repair_report_in |
|
||||
| Technician service conversation | Boundary exchange; sa_contact; 63009b5f-539e-5914-b630-ec6b7febf4d5 | Source field Repair service client @sa_control_port, owned by Pressure coordination service; target field Repair service provider @sa_technician_port, owned by Field technician. Directed exchange checkbox unchecked, so participants are unordered semantically. |
|
||||
|
||||
All three show Valve repair @sa_repair_operation in Items. A shared item does not make these relations equivalent. The conversation uses boundary ports; the other exchanges use functional ports and function endpoints.
|
||||
|
||||
Request full-path highlighting resolves the otherwise difficult bend near Assess pressure alarm and approach to the upper Repair port. Report highlighting resolves the apparent branch toward Reset valve remotely: its selected path continues to Confirm safe pressure, while the reset branch remains gray.
|
||||
|
||||
Conversation selection materially clarifies label association: the selected green route travels from the system's right square marker left of the label to an upward segment, ending at the actor's left square marker. The label remains far to the right, next to a different actor-to-function allocation stroke. The label selects the intended conversation, but its visual placement suggests the wrong nearby route when unselected. See 05 and 06.
|
||||
|
||||
Owner evidence was inspected separately using port markers and visible Parent/semantic-parent fields and tooltips, not inferred solely from shared card locations. See 13, 18 through 22.
|
||||
|
||||
## Two distinct port mappings
|
||||
|
||||
| Mapping | Alias / UUID | Semantic port endpoints |
|
||||
| --- | --- | --- |
|
||||
| Port allocation: Report repair result output | sa_port_report_out; e53b7a40-e8a3-5b3f-826d-c2b5c164a84a | Repair service provider @sa_technician_port -> Report repair result output @sa_repair_report_out |
|
||||
| Port allocation: Request field repair input | sa_port_request_in; 09eaa992-4cdf-5ea3-b748-f10fd74b8cba | Repair service provider @sa_technician_port -> Request field repair input @sa_repair_request_in |
|
||||
|
||||
Both are Port allocation relations. Their source port is owned by Field technician; their distinct target ports are owned by Repair valve in the field. They share displayed owner cards and an upper route corridor, but they have distinct port endpoints, aliases, UUIDs, and lower approach geometry. See 10 through 19.
|
||||
|
||||
### Actual attempts and wrong turns
|
||||
|
||||
1. First guessed actor-to-function stroke at (933,520), followed by another click at that point and (904,572), selected Allocation: Repair valve in the field, alias sa_repair_allocation, UUID 725f2e1b-aa2c-5615-9b1f-28da178168fa. Inspector showed Source Field technician @sa_technician and Target Repair valve in the field. This is the ordinary card allocation, not either port mapping. The wrong turn followed the visually obvious line near the misplaced conversation label. Repeated clicks did not cycle alternatives.
|
||||
2. Connections on that allocation showed REFERENCES to Field technician and Repair valve in the field. Clicking Field technician opened its Connections page. The actor's OUTGOING RELATIONSHIPS showed the ordinary allocation only; its CONTAINS section exposed Repair service provider. Thus owner-level Connections did not directly expose these port-level mappings, but a discoverable contained-port traversal did.
|
||||
3. Clicking Repair service provider showed OWNED BY Field technician, OUTGOING RELATIONSHIPS containing interface provision plus two separately named Port allocation entries, and incoming Technician service conversation. Relation row titles selected the actual relations; the distinct Open target actions instead navigate to a referenced endpoint. See 10.
|
||||
4. Clicked Port allocation: Report repair result output title, then Properties. Its entire selected path followed the actor's left square, then left and down in the tall corridor to the lower Repair port. Captured exact identity and semantic source/target fields.
|
||||
5. Clicked the now-known shared upper stroke at (806,502) twice. Report mapping selection remained; there was no visible picker or cycle. This alone does not prove a fixed preference because a mapping was already selected.
|
||||
6. Clicked provider square marker (865,451), then Connections, then Port allocation: Request field repair input title, then Properties. Request mapping was separately reachable, with a different UUID and upper Repair input endpoint.
|
||||
7. Clicking shared stroke (806,502) with request selected retained request. A blank canvas click did not clear selection in this test. Escape did clear selection. Clicking (806,502) from 0 selected selected the request mapping. Therefore the observed behavior is selection-dependent retention / no cycling, with request chosen from the cleared state in this run, not a proven universal report-first rule. The earlier progress phrase saying the shared stroke repeatedly selects report was provisional and is superseded by these observations.
|
||||
8. Clicking the lower corridor segment (806,627), below the request-port branch, selected the report mapping directly. Hence both mappings were reachable on canvas after their routes had been learned through Connections, and both were independently reachable through semantic relation entries. The low zoom and adjacent vertical paths make discovery considerably harder than access once the locations are known.
|
||||
9. Selected request input, report output, service client, request output, and report input port markers to verify visible parent ownership and aliases. Ended with Escape, 0 selected.
|
||||
|
||||
## Outcome and limitations
|
||||
|
||||
Assisted relation reading succeeds through label selection, full-path highlighting, and Inspector fields. The unselected conversation label association remains misleading. Highlighting separates the report route from apparent branches and lets a reader verify ports rather than infer semantics from cards.
|
||||
|
||||
Distinct coincident mappings are accessible through port Connections and carefully chosen segments. Repeated clicking on their shared corridor does not expose an explicit alternative list or cycle in this run. Reaching the two by semantic navigation required going through the actor's contained port; this is possible but adds several steps and requires understanding the card/port distinction. Full names and stable aliases are often clipped inside narrow dropdowns, while the Connections row body and port tooltip supply useful full names.
|
||||
|
||||
This phase does not claim route editing, label persistence, model serialization, or equivalence under edits; those belong to a separately declared edit/oracle phase. No model edits were attempted.
|
||||
|
||||
## Screenshots
|
||||
|
||||
01-02 request label selection and fields; 03-04 report selection and fields; 05-06 conversation selection, displaced highlight, endpoints and unchecked direction; 07-08 initial ordinary-allocation wrong turn; 09 actor Connections; 10 provider Connections with both mappings; 11-12 report mapping; 13 provider ownership; 14-15 request mapping; 16 cleared-state shared-stroke selection of request; 17 direct lower-stroke selection of report; 18-22 port owner/alias verification.
|
||||
|
||||
All PNGs are archived native Computer Use captures, with no synthetic rendering or image transformation.
|
||||
@@ -1,38 +0,0 @@
|
||||
from pathlib import Path
|
||||
import copy,hashlib,json,math
|
||||
root=Path(__file__).resolve().parent
|
||||
manual=root/'manual'
|
||||
a=json.loads((manual/'geometry-before.json').read_text(encoding='utf-8'))
|
||||
b=json.loads((manual/'geometry-after.json').read_text(encoding='utf-8'))
|
||||
diagram='00000000-0038-4000-8000-000000000001'
|
||||
edge='63009b5f-539e-5914-b630-ec6b7fefb4d5'
|
||||
original=a['project'];saved=b['project']
|
||||
assert original['diagrams'][diagram]['routes']==[]
|
||||
routes=saved['diagrams'][diagram]['routes']
|
||||
assert len(routes)==1 and set(routes[0])=={'edge','waypoints','label'}
|
||||
route=routes[0]
|
||||
assert route['edge']==edge and route['waypoints']==[]
|
||||
assert route['label']['fraction']==0.5
|
||||
assert set(route['label'])=={'fraction','offset'} and set(route['label']['offset'])=={'x','y'}
|
||||
assert all(math.isfinite(v) for v in route['label']['offset'].values())
|
||||
restored=copy.deepcopy(saved)
|
||||
restored['diagrams'][diagram]['routes']=[]
|
||||
assert restored==original, 'Unexpected other stored changes'
|
||||
assert a['projected_view']==b['projected_view'] and a['projected_semantic_inventory']==b['projected_semantic_inventory']
|
||||
ea={e['id']:e for e in a['routed_edges']};eb={e['id']:e for e in b['routed_edges']}
|
||||
assert ea.keys()==eb.keys()
|
||||
changed_labels=[]
|
||||
for k in ea:
|
||||
for field in ['points','projected','semantic','effective_pins','pin_fractions','custom_suspended','route_warnings']:
|
||||
assert ea[k][field]==eb[k][field], (k,field)
|
||||
if ea[k]['label']!=eb[k]['label']:changed_labels.append({'edge':k,'before':ea[k]['label'],'after':eb[k]['label']})
|
||||
old=ea[edge]['label'];new=eb[edge]['label']
|
||||
assert old['fraction']==new['fraction']==0.5 and old['anchor']==new['anchor']
|
||||
delta={key:new['center'][key]-old['center'][key] for key in ['x','y']}
|
||||
screen={'x':-48.,'y':-30.}
|
||||
inferred_zoom={key:screen[key]/delta[key] for key in ['x','y']}
|
||||
assert all(0.515<=z<0.525 for z in inferred_zoom.values()), inferred_zoom
|
||||
assert abs(inferred_zoom['x']-inferred_zoom['y'])<0.00001
|
||||
result={'status':'PASS','scope':'Complete stored Project and all 12 computed paths are conserved except the declared label metadata. Rendered labels are separately compared below.','stored_allowed_delta':route,'computed_labels_changed':changed_labels,'all_computed_paths_identical':True,'gesture':{'start_screen':[924,547],'end_screen':[876,517],'world_delta':delta,'inferred_zoom':inferred_zoom,'rounded_fit_zoom_percent':52,'method':'The predeclared screen displacement and observed center displacement must imply one zoom in the rounding interval for the visible Fit52%; no exact independent zoom was captured.'},'geometry_pins':{p.name:hashlib.sha256(p.read_bytes()).hexdigest() for p in [manual/'geometry-before.json',manual/'geometry-after.json']}}
|
||||
(manual/'geometry-comparison.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
|
||||
print(json.dumps({'status':result['status'],'changed_computed_labels':[x['edge'] for x in changed_labels],'all_paths_identical':True,'gesture':result['gesture']},indent=2))
|
||||
@@ -1,25 +0,0 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json
|
||||
root=Path(__file__).resolve().parent
|
||||
before=root/'working/eight-card.json'
|
||||
after=root/'working/project.json'
|
||||
a=json.loads(before.read_text(encoding='utf-8'))
|
||||
b=json.loads(after.read_text(encoding='utf-8'))
|
||||
differences=[]
|
||||
def compare(left,right,path=''):
|
||||
if type(left)!=type(right):
|
||||
differences.append({'path':path,'before':left,'after':right});return
|
||||
if isinstance(left,dict):
|
||||
for key in sorted(left.keys()|right.keys()):
|
||||
if key not in left or key not in right:
|
||||
differences.append({'path':path+'/'+key,'before':left.get(key),'after':right.get(key),'kind':'key change'})
|
||||
else: compare(left[key],right[key],path+'/'+key)
|
||||
elif isinstance(left,list):
|
||||
if len(left)!=len(right):
|
||||
differences.append({'path':path,'kind':'length change','before':len(left),'after':len(right)})
|
||||
for i,(x,y) in enumerate(zip(left,right)): compare(x,y,path+'/'+str(i))
|
||||
elif left!=right: differences.append({'path':path,'before':left,'after':right})
|
||||
compare(a,b)
|
||||
result={'before':{'path':str(before),'sha256':hashlib.sha256(before.read_bytes()).hexdigest()},'after':{'path':str(after),'sha256':hashlib.sha256(after.read_bytes()).hexdigest()},'differences':differences}
|
||||
(root/'manual/full-diff.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
|
||||
print(json.dumps(result,indent=2))
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"source": "6e7c4ddaf0775198384a8c4882809ea8e14b2976",
|
||||
"routing_core_source": "715036e132677dd2bc2fb37ed316d93dc9987aec",
|
||||
"fixture_probe_source": "f754ad85d3674a709d10054e6fe23079f977c547",
|
||||
"start": "2026-10-02T01:06:58.733162+00:00",
|
||||
"binary_sha256": "d55ecad4b0f75c0c9c26625e5441bef9c9360890b65bc13236c6ebfaf03d631e",
|
||||
"runtime_sha256": "f45604a12e8bcd839fd86f667c1be1cc7c4f9da2b3c69ff381ac708f0e1ae7d4",
|
||||
"fixture_sha256": "9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8",
|
||||
"fixture": "C:\\ar-diagram-01a0d717\\.local\\native-reading\\working\\eight-card.json",
|
||||
"cwd": "C:\\ar-diagram-01a0d717\\.local\\native-reading\\working",
|
||||
"path": "C:\\Windows\\System32;C:\\Windows",
|
||||
"pid": 5612,
|
||||
"exit_code": 0,
|
||||
"finished": "2026-10-02T01:30:11.251047+00:00",
|
||||
"stdout_bytes": 0,
|
||||
"stderr_bytes": 0,
|
||||
"fixture_unchanged": true
|
||||
}
|
||||
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 138 KiB |
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"before": {
|
||||
"path": "C:\\ar-diagram-01a0d717\\.local\\native-reading\\working\\eight-card.json",
|
||||
"sha256": "9db1015369f450d5810c96a01fddb8a009d57f6aafbda5182703f15ded23d9c8"
|
||||
},
|
||||
"after": {
|
||||
"path": "C:\\ar-diagram-01a0d717\\.local\\native-reading\\working\\project.json",
|
||||
"sha256": "39572f8ab176f7b8ac8933a308dcf7b127aa15e3d4f627ef604325a5275812f2"
|
||||
},
|
||||
"differences": [
|
||||
{
|
||||
"path": "/diagrams/00000000-0038-4000-8000-000000000001/routes",
|
||||
"kind": "length change",
|
||||
"before": 0,
|
||||
"after": 1
|
||||
}
|
||||
]
|
||||
}
|
||||