Merge commit 'ad7feb5' into codex/state-integration
This commit is contained in:
@@ -28,6 +28,11 @@ mod lifecycle_tests;
|
||||
#[path = "diagram/port_hit_tests.rs"]
|
||||
mod port_hit_tests;
|
||||
|
||||
#[path = "diagram/port_labels.rs"]
|
||||
mod port_labels;
|
||||
pub use port_labels::PortLabels;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct DiagramCanvas<'a> {
|
||||
pub project: &'a Project,
|
||||
pub diagram: Id,
|
||||
@@ -901,7 +906,7 @@ impl canvas::Program<Message> for DiagramCanvas<'_> {
|
||||
renderer: &Renderer,
|
||||
_: &Theme,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
_: mouse::Cursor,
|
||||
) -> Vec<canvas::Geometry> {
|
||||
let mut f = Frame::new(renderer, bounds.size());
|
||||
f.fill_rectangle(
|
||||
@@ -922,17 +927,8 @@ impl canvas::Program<Message> for DiagramCanvas<'_> {
|
||||
}
|
||||
f.translate(self.pan);
|
||||
f.scale(self.zoom);
|
||||
// Canvas text is painted after paths within each geometry. A separate
|
||||
// frame keeps the port tooltip above underlying edge labels. Its text
|
||||
// stays legible at overview zoom levels and within the canvas bounds.
|
||||
let mut port_label = Frame::new(renderer, bounds.size());
|
||||
let scene = self.scene(state);
|
||||
let view = &scene.view;
|
||||
let labeled_port = cursor
|
||||
.position_in(bounds)
|
||||
.and_then(|p| self.hit_port(view, p))
|
||||
.or_else(|| view.ports.iter().find(|p| p.element == self.selected))
|
||||
.map(|p| p.element);
|
||||
let containers = view
|
||||
.nodes
|
||||
.iter()
|
||||
@@ -1082,68 +1078,6 @@ impl canvas::Program<Message> for DiagramCanvas<'_> {
|
||||
if matches!(glyph, PortGlyph::Unspecified | PortGlyph::Legacy) {
|
||||
f.fill(&Path::circle(center, 1.5), color);
|
||||
}
|
||||
if labeled_port == Some(port.element) {
|
||||
let name = short(self.project.named(port.element), 40);
|
||||
let owner = self.project.elements[&port.element]
|
||||
.parent
|
||||
.map(|id| short(self.project.named(id), 40))
|
||||
.unwrap_or_default();
|
||||
let alias = &self.project.elements[&port.element].alias;
|
||||
let alias = if alias.chars().count() > 48 {
|
||||
format!(
|
||||
"@{}…{}",
|
||||
alias.chars().take(22).collect::<String>(),
|
||||
alias
|
||||
.chars()
|
||||
.skip(alias.chars().count() - 24)
|
||||
.collect::<String>()
|
||||
)
|
||||
} else {
|
||||
format!("@{alias}")
|
||||
};
|
||||
let width = ((name
|
||||
.chars()
|
||||
.count()
|
||||
.max(owner.chars().count())
|
||||
.max(alias.chars().count()) as f32
|
||||
* 7.)
|
||||
+ 16.)
|
||||
.min((bounds.width - 8.).max(0.));
|
||||
let height = 60.;
|
||||
let anchor = Point::new(
|
||||
center.x * self.zoom + self.pan.x + 12.,
|
||||
center.y * self.zoom + self.pan.y + 12.,
|
||||
);
|
||||
let origin = Point::new(
|
||||
anchor.x.clamp(4., (bounds.width - width - 4.).max(4.)),
|
||||
anchor.y.clamp(4., (bounds.height - height - 4.).max(4.)),
|
||||
);
|
||||
let background =
|
||||
Path::rounded_rectangle(origin, Size::new(width, height), 4.into());
|
||||
port_label.fill(&background, Color::WHITE);
|
||||
port_label.stroke(&background, Stroke::default().with_color(style::LINE));
|
||||
port_label.fill_text(Text {
|
||||
content: name,
|
||||
position: origin + Vector::new(8., 4.),
|
||||
color: style::TEAL,
|
||||
size: 12.into(),
|
||||
..Default::default()
|
||||
});
|
||||
port_label.fill_text(Text {
|
||||
content: owner,
|
||||
position: origin + Vector::new(8., 22.),
|
||||
color: style::MUTED,
|
||||
size: 11.into(),
|
||||
..Default::default()
|
||||
});
|
||||
port_label.fill_text(Text {
|
||||
content: alias,
|
||||
position: origin + Vector::new(8., 40.),
|
||||
color: style::MUTED,
|
||||
size: 11.into(),
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(edge) = scene.routed.edges.get(&self.selected)
|
||||
&& !edge.custom_suspended
|
||||
@@ -1285,11 +1219,7 @@ impl canvas::Program<Message> for DiagramCanvas<'_> {
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
vec![
|
||||
f.into_geometry(),
|
||||
port_label.into_geometry(),
|
||||
overlay.into_geometry(),
|
||||
]
|
||||
vec![f.into_geometry(), overlay.into_geometry()]
|
||||
}
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
//! Passive renderer layer for port identity feedback. Iced batches every text
|
||||
//! primitive after meshes within one GPU layer, even across Canvas frames.
|
||||
//! A second stacked canvas places the complete tooltip above diagram text.
|
||||
use super::*;
|
||||
|
||||
pub struct PortLabels<'a>(pub DiagramCanvas<'a>);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct State {
|
||||
view: RefCell<Option<(Context, ProjectedView)>>,
|
||||
context: Option<Context>,
|
||||
held_buttons: u8,
|
||||
}
|
||||
|
||||
impl canvas::Program<Message> for PortLabels<'_> {
|
||||
type State = State;
|
||||
|
||||
fn update(
|
||||
&self,
|
||||
state: &mut State,
|
||||
event: &canvas::Event,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
) -> Option<Action<Message>> {
|
||||
if state.context != Some(self.0.context) {
|
||||
state.context = Some(self.0.context);
|
||||
state.held_buttons = 0;
|
||||
}
|
||||
let button_mask = |button| match button {
|
||||
mouse::Button::Left => 1,
|
||||
mouse::Button::Middle => 2,
|
||||
_ => 0,
|
||||
};
|
||||
match event {
|
||||
canvas::Event::Mouse(mouse::Event::ButtonPressed(button)) if cursor.is_over(bounds) => {
|
||||
state.held_buttons |= button_mask(*button)
|
||||
}
|
||||
canvas::Event::Mouse(mouse::Event::ButtonReleased(button)) => {
|
||||
state.held_buttons &= !button_mask(*button)
|
||||
}
|
||||
canvas::Event::Window(iced::window::Event::Unfocused) => state.held_buttons = 0,
|
||||
canvas::Event::Keyboard(iced::keyboard::Event::KeyPressed { key, .. })
|
||||
if *key == iced::keyboard::Key::Named(iced::keyboard::key::Named::Escape) =>
|
||||
{
|
||||
state.held_buttons = 0
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Never capture input: every event still reaches the interactive canvas.
|
||||
matches!(event, canvas::Event::Mouse(_)).then(Action::request_redraw)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
state: &State,
|
||||
renderer: &Renderer,
|
||||
_: &Theme,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
) -> Vec<canvas::Geometry> {
|
||||
if state.context == Some(self.0.context) && state.held_buttons != 0 {
|
||||
return vec![];
|
||||
}
|
||||
let canvas = &self.0;
|
||||
let mut cached = state.view.borrow_mut();
|
||||
if cached
|
||||
.as_ref()
|
||||
.is_none_or(|(context, _)| *context != canvas.context)
|
||||
{
|
||||
*cached = Some((canvas.context, project_view(canvas.project, canvas.diagram)));
|
||||
}
|
||||
let view = &cached.as_ref().unwrap().1;
|
||||
let Some(port) = cursor
|
||||
.position_in(bounds)
|
||||
.and_then(|p| canvas.hit_port(view, p))
|
||||
.or_else(|| view.ports.iter().find(|p| p.element == canvas.selected))
|
||||
else {
|
||||
return vec![];
|
||||
};
|
||||
let center = point(port.position);
|
||||
let mut port_label = Frame::new(renderer, bounds.size());
|
||||
|
||||
let name = short(canvas.project.named(port.element), 40);
|
||||
let owner = canvas.project.elements[&port.element]
|
||||
.parent
|
||||
.map(|id| short(canvas.project.named(id), 40))
|
||||
.unwrap_or_default();
|
||||
let alias = &canvas.project.elements[&port.element].alias;
|
||||
let alias = if alias.chars().count() > 48 {
|
||||
format!(
|
||||
"@{}…{}",
|
||||
alias.chars().take(22).collect::<String>(),
|
||||
alias
|
||||
.chars()
|
||||
.skip(alias.chars().count() - 24)
|
||||
.collect::<String>()
|
||||
)
|
||||
} else {
|
||||
format!("@{alias}")
|
||||
};
|
||||
let width = ((name
|
||||
.chars()
|
||||
.count()
|
||||
.max(owner.chars().count())
|
||||
.max(alias.chars().count()) as f32
|
||||
* 7.)
|
||||
+ 16.)
|
||||
.min((bounds.width - 8.).max(0.));
|
||||
let height = 60.;
|
||||
let anchor = Point::new(
|
||||
center.x * canvas.zoom + canvas.pan.x + 12.,
|
||||
center.y * canvas.zoom + canvas.pan.y + 12.,
|
||||
);
|
||||
let origin = Point::new(
|
||||
anchor.x.clamp(4., (bounds.width - width - 4.).max(4.)),
|
||||
anchor.y.clamp(4., (bounds.height - height - 4.).max(4.)),
|
||||
);
|
||||
let background = Path::rounded_rectangle(origin, Size::new(width, height), 4.into());
|
||||
port_label.fill(&background, Color::WHITE);
|
||||
port_label.stroke(&background, Stroke::default().with_color(style::LINE));
|
||||
port_label.fill_text(Text {
|
||||
content: name,
|
||||
position: origin + Vector::new(8., 4.),
|
||||
color: style::TEAL,
|
||||
size: 12.into(),
|
||||
..Default::default()
|
||||
});
|
||||
port_label.fill_text(Text {
|
||||
content: owner,
|
||||
position: origin + Vector::new(8., 22.),
|
||||
color: style::MUTED,
|
||||
size: 11.into(),
|
||||
..Default::default()
|
||||
});
|
||||
port_label.fill_text(Text {
|
||||
content: alias,
|
||||
position: origin + Vector::new(8., 40.),
|
||||
color: style::MUTED,
|
||||
size: 11.into(),
|
||||
..Default::default()
|
||||
});
|
||||
vec![port_label.into_geometry()]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{app::App, model_menu};
|
||||
use canvas::Program;
|
||||
|
||||
fn fixture() -> (App, Id) {
|
||||
let mut project = Project::empty();
|
||||
let owner = project.add(Kind::Function, "Send report", 100., 150.);
|
||||
let port = Id::new_v4();
|
||||
project.elements.insert(
|
||||
port,
|
||||
make_port(
|
||||
&project,
|
||||
port,
|
||||
owner,
|
||||
"Report output",
|
||||
PortContract::FunctionOutput {
|
||||
outgoing_items: vec![],
|
||||
},
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
(App::with_project(project), port)
|
||||
}
|
||||
|
||||
fn program(app: &App) -> PortLabels<'_> {
|
||||
PortLabels(DiagramCanvas {
|
||||
project: app.project(),
|
||||
diagram: app.active_diagram.unwrap(),
|
||||
selected: app.selected,
|
||||
zoom: 1.,
|
||||
pan: Vector::ZERO,
|
||||
context: app.route_context().unwrap(),
|
||||
selected_bend: None,
|
||||
editable: true,
|
||||
connection: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn bounds() -> Rectangle {
|
||||
Rectangle::new(Point::new(120., 80.), Size::new(900., 600.))
|
||||
}
|
||||
|
||||
// Stack visits this canvas first. Every event must remain available to the
|
||||
// interactive child, and this layer must never levitate its cursor.
|
||||
fn passive(labels: &PortLabels<'_>, state: &mut State, event: canvas::Event, at: Point) {
|
||||
let cursor = mouse::Cursor::Available(at);
|
||||
if let Some(action) = labels.update(state, &event, bounds(), cursor) {
|
||||
let (message, _, status) = action.into_inner();
|
||||
assert!(message.is_none());
|
||||
assert_eq!(status, iced::event::Status::Ignored);
|
||||
}
|
||||
assert_eq!(
|
||||
labels.mouse_interaction(state, bounds(), cursor),
|
||||
mouse::Interaction::None
|
||||
);
|
||||
}
|
||||
|
||||
fn mouse(labels: &PortLabels<'_>, state: &mut State, event: mouse::Event) {
|
||||
passive(
|
||||
labels,
|
||||
state,
|
||||
canvas::Event::Mouse(event),
|
||||
bounds().center(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn leaving_and_reentering_keeps_suppression_until_each_held_button_releases() {
|
||||
let (app, _) = fixture();
|
||||
let labels = program(&app);
|
||||
let mut state = State::default();
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonPressed(mouse::Button::Left),
|
||||
);
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonPressed(mouse::Button::Middle),
|
||||
);
|
||||
mouse(&labels, &mut state, mouse::Event::CursorLeft);
|
||||
mouse(&labels, &mut state, mouse::Event::CursorEntered);
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::CursorMoved {
|
||||
position: bounds().center(),
|
||||
},
|
||||
);
|
||||
assert_ne!(
|
||||
state.held_buttons, 0,
|
||||
"Preview geometry remains active across reentry"
|
||||
);
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonReleased(mouse::Button::Right),
|
||||
);
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonReleased(mouse::Button::Left),
|
||||
);
|
||||
assert_ne!(state.held_buttons, 0, "Middle-button pan is still held");
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonReleased(mouse::Button::Middle),
|
||||
);
|
||||
assert_eq!(state.held_buttons, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn menu_epoch_clears_suppression_when_the_overlay_consumes_release() {
|
||||
let (mut app, port) = fixture();
|
||||
let before = app.document.bundle().clone();
|
||||
let mut state = State::default();
|
||||
mouse(
|
||||
&program(&app),
|
||||
&mut state,
|
||||
mouse::Event::ButtonPressed(mouse::Button::Left),
|
||||
);
|
||||
let old_context = state.context;
|
||||
let _ = app.update(model_menu::open(port, bounds().center()));
|
||||
assert!(app.model_menu.is_some());
|
||||
assert_ne!(old_context, app.route_context());
|
||||
// Left release and dismissal input are captured by the root popup.
|
||||
let _ = app.update(Message::Menu(model_menu::Event::Close));
|
||||
passive(
|
||||
&program(&app),
|
||||
&mut state,
|
||||
canvas::Event::Window(iced::window::Event::RedrawRequested(
|
||||
std::time::Instant::now(),
|
||||
)),
|
||||
bounds().center(),
|
||||
);
|
||||
assert_eq!(state.held_buttons, 0);
|
||||
assert_eq!(state.context, app.route_context());
|
||||
assert_eq!(app.document.bundle(), &before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outside_presses_do_not_suppress_and_cancel_or_focus_loss_clear_held_buttons() {
|
||||
let (app, _) = fixture();
|
||||
let labels = program(&app);
|
||||
let mut state = State::default();
|
||||
passive(
|
||||
&labels,
|
||||
&mut state,
|
||||
canvas::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)),
|
||||
Point::ORIGIN,
|
||||
);
|
||||
assert_eq!(state.held_buttons, 0);
|
||||
for event in [
|
||||
canvas::Event::Keyboard(iced::keyboard::Event::KeyPressed {
|
||||
key: iced::keyboard::Key::Named(iced::keyboard::key::Named::Escape),
|
||||
modified_key: iced::keyboard::Key::Named(iced::keyboard::key::Named::Escape),
|
||||
physical_key: iced::keyboard::key::Physical::Code(
|
||||
iced::keyboard::key::Code::Escape,
|
||||
),
|
||||
location: iced::keyboard::Location::Standard,
|
||||
modifiers: iced::keyboard::Modifiers::empty(),
|
||||
text: None,
|
||||
repeat: false,
|
||||
}),
|
||||
canvas::Event::Window(iced::window::Event::Unfocused),
|
||||
] {
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonPressed(mouse::Button::Left),
|
||||
);
|
||||
mouse(
|
||||
&labels,
|
||||
&mut state,
|
||||
mouse::Event::ButtonPressed(mouse::Button::Middle),
|
||||
);
|
||||
passive(&labels, &mut state, event, bounds().center());
|
||||
assert_eq!(state.held_buttons, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn passive_layer_leaves_port_drag_selection_and_commit_with_the_interactive_canvas() {
|
||||
let (app, port) = fixture();
|
||||
let labels = program(&app);
|
||||
let view = project_view(app.project(), labels.0.diagram);
|
||||
let projected = view.ports.iter().find(|p| p.element == port).unwrap();
|
||||
let owner = view.nodes.iter().find(|n| n.id == projected.owner).unwrap();
|
||||
let screen = |p: Position| point(p) + Vector::new(bounds().x, bounds().y);
|
||||
let start = screen(projected.position);
|
||||
let end = screen(projection::port_anchor_position(
|
||||
owner,
|
||||
PortAnchorSide::Top,
|
||||
0.3,
|
||||
));
|
||||
let mut state = State::default();
|
||||
let mut interactive = super::super::State::default();
|
||||
let mut messages = Vec::new();
|
||||
for event in [
|
||||
mouse::Event::CursorMoved { position: start },
|
||||
mouse::Event::ButtonPressed(mouse::Button::Left),
|
||||
mouse::Event::CursorMoved { position: end },
|
||||
mouse::Event::ButtonReleased(mouse::Button::Left),
|
||||
] {
|
||||
let event = canvas::Event::Mouse(event);
|
||||
passive(&labels, &mut state, event.clone(), end);
|
||||
if let Some(action) = labels.0.update(
|
||||
&mut interactive,
|
||||
&event,
|
||||
bounds(),
|
||||
mouse::Cursor::Available(end),
|
||||
) {
|
||||
let (message, _, _) = action.into_inner();
|
||||
messages.extend(message);
|
||||
}
|
||||
}
|
||||
assert!(matches!(messages.first(), Some(Message::Select(id)) if *id == port));
|
||||
assert!(
|
||||
matches!(messages.last(), Some(Message::PortAnchor(crate::port_edit::Event::Commit(_, _, anchor))) if anchor.port == port && anchor.side == PortAnchorSide::Top)
|
||||
);
|
||||
assert_eq!(messages.len(), 2);
|
||||
assert_eq!(state.held_buttons, 0);
|
||||
}
|
||||
}
|
||||
@@ -382,24 +382,26 @@ fn diagram(app: &App) -> View<'_, Message> {
|
||||
.spacing(10)
|
||||
.align_y(iced::Center);
|
||||
let canvas: View<'_, Message> = if let Some(id) = app.active_diagram {
|
||||
widget::sensor(
|
||||
widget::canvas(DiagramCanvas {
|
||||
project: app.project(),
|
||||
diagram: id,
|
||||
selected: app.selected,
|
||||
zoom: app.zoom,
|
||||
pan: app.pan,
|
||||
context: app.route_context().unwrap(),
|
||||
selected_bend: app
|
||||
.selected_bend
|
||||
.filter(|(edge, _)| *edge == app.selected)
|
||||
.map(|(_, i)| i),
|
||||
editable: !app.draft_dirty() && !app.source_dirty(),
|
||||
connection: app.connection.as_ref(),
|
||||
})
|
||||
.width(Fill)
|
||||
.height(Fill),
|
||||
)
|
||||
let program = DiagramCanvas {
|
||||
project: app.project(),
|
||||
diagram: id,
|
||||
selected: app.selected,
|
||||
zoom: app.zoom,
|
||||
pan: app.pan,
|
||||
context: app.route_context().unwrap(),
|
||||
selected_bend: app
|
||||
.selected_bend
|
||||
.filter(|(edge, _)| *edge == app.selected)
|
||||
.map(|(_, i)| i),
|
||||
editable: !app.draft_dirty() && !app.source_dirty(),
|
||||
connection: app.connection.as_ref(),
|
||||
};
|
||||
widget::sensor(widget::stack![
|
||||
widget::canvas(program).width(Fill).height(Fill),
|
||||
widget::canvas(crate::diagram::PortLabels(program))
|
||||
.width(Fill)
|
||||
.height(Fill),
|
||||
])
|
||||
.on_show(Message::CanvasResized)
|
||||
.on_resize(Message::CanvasResized)
|
||||
.into()
|
||||
|
||||
@@ -38,3 +38,9 @@
|
||||
- Contextual actions use a controlled Iced overlay and captured semantic target plus document/revision/view context. Menus reuse existing handlers, and opening a menu does not select/apply another draft. Canvas focus scopes routing keys; Actions is an accessible alternative to right-click. Source files use a folder tree with exact paths and aggregate draft/diagnostic markers.
|
||||
- Port anchors are per-placement presentation records with four sides and normalized offsets. Automatic sides use port direction and visible peer geometry; explicit anchors do not change owner minimum dimensions. Canvas, routing, Fit and SVG share projected anchors and side normals. Graphical reparent batches old-owner anchor cleanup with semantic reparent; raw source and API remain strict and require explicit repair.
|
||||
- Direct connections use explicit Select/move and exchange palette tools. Compatible visible endpoints are highlighted; click-click or drag creates one ordinary validated command. Function-card gestures use the existing automatic port planner. Tool invocation, blank-canvas restart, Escape and model/view changes invalidate old gesture contexts. No project clone or whole-model compile occurs per highlighted candidate; final commit still validates the complete model/source change.
|
||||
- Port identity feedback is a passive stacked Canvas: Iced Frame separation alone
|
||||
does not create GPU layering. The independent native overprint reproduction
|
||||
established the need; input stays with the existing interactive child.
|
||||
- Each checkout uses a distinct Cargo target directory. A shared-target Linux run
|
||||
reused a different worktree's test executable; only explicitly rebuilt main
|
||||
results count as evidence.
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ The current forms are a closed typed-record adapter, not a second metamodel. Exp
|
||||
|
||||
Nested source ownership and persistent REST bundles are implemented and verified: Windows minimum-size source-to-graphics, nested reparent/source/Undo/Redo/Save/reopen, recovery, rebuilt Linux source/history/Save/reopen, independent review and both platform suites passed. Preserve the existing grammar/updater and separate allocation/order semantics.
|
||||
|
||||
Current user-directed sequence: finish native contextual-menu/source-tree acceptance; then ship draggable per-placement port sides and intelligent automatic placement; then direct diagram connection tools for OA interactions, functional exchanges and boundary exchanges. Port placement is presentation state, and drawing an exchange uses the existing typed semantic command boundary. Select/move and Connect are explicit modes; connection targets highlight only compatible visible endpoints. A completed drag commits once, retains text/REST parity, and supports Undo/Redo/Save/reopen. Verify all four port sides, nested owners, routing/pins, compatible and incompatible endpoints, zoom, Escape, stale gestures, and minimum Windows/Linux layouts. The independently tested state-core slice is preserved in its worktree until these latest usability priorities are integrated; all broader release milestones remain required.
|
||||
The user-directed contextual-menu/source-tree, movable-port and direct-connection milestone has scoped Windows/Linux native acceptance. See release-port-drawing.md for exact builds, saved trials and minimum-size boundaries. Continue direct state-machine editing in the isolated state-integration checkout: persist typed machine context, use shared state/route geometry, retain drafts until accepted document commit, then verify creation, movement, transition drawing/reconnection, undo and reopen. This first behavior slice precedes scenario/process gestures; all broader release milestones remain required.
|
||||
|
||||
The user-directed actor/system port and model-navigation milestone is accepted: visible Add port → Connect boundary exchange, grouped roots, focused containment, breadcrumbs, contextual search and paging, clear full-depth outline, and separate allocations. Native Windows authoring/save/reopen, 251-root paging, 12-level navigation, 1440×900/1100×700 inspection, rebuilt Linux save/reopen and single-line font correction passed. Independent requirements, correctness, native UI and simplicity findings are addressed; release-explorer-usability.md records exact evidence and remaining performance boundaries. Resume source recovery acceptance and the release milestones below; the full scope remains intact.
|
||||
|
||||
|
||||
+125
-54
@@ -2,75 +2,146 @@
|
||||
|
||||
## Objective and current phase
|
||||
|
||||
The first-release goal remains active and incomplete: a Rust/Iced OA and SA/System Architecture tool for system engineers with equivalent graphical, textual and REST semantics, hierarchical diagrams and typed ports, modular source projects, artifact traceability, direct behavior editing, offline help, and Windows/Linux release evidence. The authoritative objective is attachment `07aee762-7d27-4cbe-81c3-2e82c7170711/goal-objective.md`, fully read on 2026-09-05. PLAN.md, TASK_LEDGER.md and release-semantics-audit.md retain the broader scope.
|
||||
The first-release goal remains active and incomplete. Deliver Rust/Iced Operational
|
||||
Analysis and System Analysis/System Architecture for system engineers, equivalent
|
||||
graphical/textual/REST semantics, hierarchical diagrams and typed ports, modular
|
||||
source projects, artifact traceability, editable behavior, useful offline help,
|
||||
and Windows/Linux release evidence. Later Arcadia layers remain future releases.
|
||||
Authoritative objective: attachment
|
||||
`07aee762-7d27-4cbe-81c3-2e82c7170711/goal-objective.md`, reread 2026-09-06.
|
||||
PLAN.md, TASK_LEDGER.md and release-semantics-audit.md retain full release scope.
|
||||
|
||||
The editable connection-routing milestone is accepted at `23535b4` with viewport follow-up `366ce44`. Per-diagram authoring, obstacle-aware geometry, typed/nested workshop movement, save/reopen, SVG and minimum-size gestures are verified. Commit `65fa9ab` resolved all six reproduced default SA label-overlap pairs. Fresh correctness and native UI review found no unresolved material routing finding; root also verified the actual Linux application and the viewport follow-up. The broader first release remains incomplete; production text authoring is active. See release-routing-verification.md and release-routing-linux.md for exact evidence and limitations. Root alone operates native applications.
|
||||
The latest user-directed drawing/port/menu/source-tree milestone is accepted at
|
||||
`fef2e0d` plus the pending tooltip-layer follow-up. It does not complete the release.
|
||||
Root now integrates direct state-machine editing in an isolated worktree. There
|
||||
is meaningful implementation, independent review and real runtime progress; no
|
||||
external blocker or disk blocker exists.
|
||||
|
||||
## Completed foundations
|
||||
## Accepted foundations and evidence
|
||||
|
||||
Nested source/REST integration checkpoint: production parser and iterative structural writer are implemented; REST persists the accepted bundle and model in one ETag envelope. Final workspace runs passed 422 Windows and 425 Linux tests; strict workspace Clippy, formatting and Windows/Linux builds passed. Actual server import, comment-only revision, cross-file reparent, stale ETag and exact restart/conditional GET passed. Owner-opening-line comment reassignment and equal-model delete/recreate provenance defects were reproduced, fixed and reverified. Independent parser/writer/model-source boundary reviews found no remaining material findings; fresh spawn was unavailable because of the thread limit, so workers reviewed one another's artifacts. Strict language/API reST rendering passed after correcting an API heading underline. Root's Windows nested reparent/arrange/source/Undo/Redo/Save/reopen passed with 22 objects,13 links,0 checks. Independent minimum-size/source-created port QA passed. Root also verified Linux nested source edit/Undo/Redo/Save/reopen; the Linux instance closed normally with an empty log. Evidence: release-source-integration.md.
|
||||
- Typed OA/SA model, schema 3 ports, validated atomic commands and ordinary history
|
||||
are shared across three Rust crates. Typed contracts and migration are documented
|
||||
in release-port-contract.md, release-port-core.md and release-port-migration.md.
|
||||
Desktop typed authoring checkpoint `fa096ce` passed native creation, generation,
|
||||
undo/redo and persistence. Original Capella was operated in a disposable workspace;
|
||||
exact observed semantics/workflows: release-capella-workflow-benchmark.md.
|
||||
- Explorer/port discovery `d364d3c`: visible Add port, grouped roots, focused children,
|
||||
breadcrumbs, contextual search/paging and full-depth outline. Windows port/Standard
|
||||
exchange, 251-root paging, 12-level navigation and 1100x700 trials passed; rebuilt
|
||||
Linux save/reopen/font correction passed. See release-explorer-usability.md.
|
||||
- Editable routes `23535b4`, viewport fix `366ce44`, automatic labels `65fa9ab`:
|
||||
authored bends/labels, nested group movement, folding/restoration, undo/redo,
|
||||
save/reopen, SVG and minimum-size gestures passed native and independent review.
|
||||
See release-routing-verification.md and release-routing-linux.md. Dense optimized
|
||||
full solve measured119ms; arbitrary dense crossings remain possible.
|
||||
- Nested source and coupled hosted source/model checkpoint `4e8575b`: source3
|
||||
element nesting/includes, token/provenance-aware structural writes, exact model
|
||||
source history, retained drafts and safe Save All/recovery. Full422 Windows and
|
||||
425 Linux tests, strict checks and builds passed at that checkpoint. Actual REST
|
||||
import/comment-only revision/cross-file reparent/stale ETag/restart passed.
|
||||
Windows/Linux source and nested graphical edits, save/reopen and recovery were
|
||||
exercised. See release-source-integration.md. Experiments remain evidence only;
|
||||
do not adopt their independent parser/writer.
|
||||
|
||||
Historical start of this continuation (superseded by the active checkpoint below): nested source/REST is committed at `4e8575b`. Independent Windows source-created Standard actor port, boundary-exchange entry, Undo/Redo and Save/reopen passed at 1100×700; the isolated QA window closed normally. Linux native nesting acceptance passed (source comment/history/save/reopen and rendered hierarchy; cross-file graphical reparent was exercised on Windows). Original Windows window 6228978 contains unsaved user work: do not save, reset or close it. Root again owns native input. The state-core worker owns only oa-core in isolated worktree `D:/CodexBuilds/Capella2-state-diagram-core`, branch `codex/state-diagram-core`; root integrates after review. The latest user request prioritizes contextual right-click menus and removes permanent bend buttons. Root owns desktop integration; explorer_usability_review owns only the new reusable context_menu.rs; source_integration_map maps existing actions read-only. Native source recovery acceptance already passed; no blocker and broader release scope is unchanged.
|
||||
## Drawing acceptance — current main checkout
|
||||
|
||||
- The user-directed explorer/port usability milestone is accepted. Add port is visible on participants, and selected component ports expose Connect boundary exchange. The browser uses grouped roots, focused direct children, breadcrumbs, paged contextual search and Locate; the outline keeps real depth, guides and single-line labels with full-name tooltips. Root created two Standard ports and a Boundary Exchange, exercised Undo/Redo, Save/reopen, duplicate-name search, 251-root paging and 12-level navigation. Independent native review and root's final Windows build passed at 1100×700; actual rebuilt Linux save/reopen and font-fix inspection passed. Full Windows workspace tests passed 382, followed by all 138 desktop tests; Linux full workspace passed 386. Strict checks and final Windows/Linux builds passed. Slow picker, stale reparent focus, deep-row cost, collapsed header sizing, scroll reset and font wrapping findings are fixed. Exact scope, hashes and evidence: release-explorer-usability.md.
|
||||
- Source integration checkpoint `3c87576` passed full366 Windows tests; its draft-history cap follow-up passed122 desktop tests and strict workspace Clippy. Root ran native build SHA256 `FCA6140E835B17AE4FAB003B0DAC38D7D820DD36C7559F536BA3CC607E30FE51`: opened two included buffers, typed separate rationale comments, switched with drafts retained, Apply all, model Undo/Redo, then Save All to `ui-source-project/native-source-trial.arcadia`. The entry is1496 bytes with20 other included files; both authored comments are present on disk and the UI reports all changes saved,41objects/25links/0checks. Runtime log is empty; the window closed normally (exec session99563 exited0). Those initially pending native source reopen/failure/minimum-size checks were subsequently completed at the nested-source checkpoint above.
|
||||
- Fresh source integration review at 3c87576 reproduced property-draft loss and diagnostic-only recovery state. Both are fixed in the current app: guards retain both drafts, and durable pending_recovery survives typing/lint, missing entries and initial Save failure. Four real-journal recovery tests and source/property collision tests pass in the full workspace run. The bounded reviews are complete; all agents released file/native ownership to root. Frozen source probe evidence: D:/CodexBuilds/Capella2-source-app-independent/REVIEW.md. The explorer Linux trial additionally verified failed Save to a missing directory retained the model and successful retry saved all files; interrupted-journal UI recovery was subsequently verified in the source-recovery milestone above.
|
||||
`93fd32c` fixes candidate scaling without weakening validation; `35133de` supplies
|
||||
persisted four-side normalized port anchors. `fef2e0d` adds direct palette drawing,
|
||||
shared automatic labels, contextual menus and the source folder tree. OA Interaction,
|
||||
SA Functional Exchange and Boundary Exchange accept click-click or drag. Function
|
||||
cards create/reuse typed ports atomically. Compatible targets highlight; Standard
|
||||
and Flow contracts remain distinct. Pan retains source; Escape cancels.
|
||||
|
||||
- Branch `codex/release1-engineering`; baseline `93ba83d`, hierarchy `c7101b9`, drag selection `2ef16dc`, typed core/schema 3 merge `757ab88`, alias and batch lifecycle corrections `e41b8de`.
|
||||
- Typed desktop integration `fa096ce` provides contextual function/component ports, FE endpoint and exchange-item choices, generation, resolution, split and synchronization with semantic previews. Legacy migration, Standard/Flow distinctions and independent orientation are retained. Independent findings and native-discovered no-op synchronization and SA-only initial-perspective defects were fixed.
|
||||
- Native typed-port trials created real function endpoints and exchanges, supplementary output/items, and a Standard component implementation with two port allocations and an exchange allocation. Undo/redo and save passed with zero model checks. Reviewed reopen entered SA correctly; unchanged synchronization disabled Apply. The long-reference review modal was inspected at 1440×900 and 1100×700. Evidence and fixtures are under `D:/CodexBuilds/Capella2-release1-01a06e2e/ui-typed-ports` and `ui-typed-ports-reviewed`.
|
||||
- Source bundle foundation `06b3384` and token-preserving updater `dbc8971` passed 160 core tests, including 30 source-project tests, and strict core Clippy at that checkpoint. This was the initial core-only checkpoint; production editor, filesystem Save All/conflict handling and REST bundles were subsequently integrated at 4e8575b.
|
||||
- Isolated source authoring comparison `c5788fc` and nested writeback experiment `2dd17aa` passed 23 experiment tests and strict Clippy. An independent executable probe at `D:/CodexBuilds/Capella2-source-writeback-independent/probe.log` reproduced positional list-comment misattachment after item reorder, rejection of a valid description edit on port shorthand, and unsupported occurrence deletion. The same comment-reorder probe retained attachment in the production updater. Complete model equality alone does not protect comment meaning. Extend the production parser/span index and shared updater for selected nesting/shorthand constructs; do not copy the experiment into a parallel production parser/writer. Freeze comment ownership, exact source Undo and full edit/delete support before adoption. `experiments/source-authoring/WRITEBACK.md` retains the bounded evidence; production syntax is not yet adopted.
|
||||
- R1 process topology, R2 mission/capability, R4 scenarios and R5 events/states are implemented at the semantic/form level. Full native authoring acceptance and direct behavior canvas gestures remain required; release-state-gesture-design.md records the proposed first vertical slice.
|
||||
Independent review reproduced batched-pointer click corruption and overview port
|
||||
mispicking. Ordered CursorMoved coordinates, explicit context epochs and nearest
|
||||
port glyph picking fix these, with production regressions. Native review then
|
||||
reproduced port-tooltip overprint: separate Frames still share an Iced GPU layer.
|
||||
The fix uses a passive second stacked Canvas (a real renderer layer). It preserves
|
||||
interactive child state/input and resets held-button suppression on context change,
|
||||
matching releases, Escape and focus loss. CursorLeft alone does not end suppression.
|
||||
|
||||
## Routing implementation and verification
|
||||
Evidence is in release-port-drawing.md and release-context-menus.md. Exact native
|
||||
review report: `D:/CodexBuilds/Capella2-release1-01a06e2e/drawing-independent-native-review.md`.
|
||||
Windows independent trials passed Standard rejection/completion, automatic function
|
||||
ports, undo/redo, save/reopen and1100x700. Overprint was reproduced on9A7FF074 and
|
||||
closed on3F534C67 at1440x900 and1100x700. Root tested final1EEBDC3C: first port drag,
|
||||
menu outside dismissal, first repeated drag, direct FE, readable identity and Save.
|
||||
Saved trial: `ui-port-tooltip-final/project.arcadia`,41objects/26links/0checks.
|
||||
|
||||
- `4e5a88d`: per-diagram `EdgeRoute` pins and label placement, atomic set/remove commands, validation, delete/reidentify cleanup, compatible empty defaults, group movement and layout translation. Routes refer to existing relation/trace IDs and do not duplicate semantic identity.
|
||||
- `a7c6f96`: equivalent source, source-project update, JSON and REST behavior, located validation, OpenAPI and reST contracts.
|
||||
- `68b1eff`: shared deterministic orthogonal routing and geometry for typed ports, nested obstacles, labels, bounds and collapse suspension. Desktop draw, hit testing, gesture previews, Fit and SVG use this geometry.
|
||||
- `30c7db1`: label-only edits preserve the settled polyline and warnings; single-edge previews retain settled per-edge routing budgets. `65fa9ab` adds stable bounded automatic label placement, reducing the workshop's six reproduced label-overlap pairs to zero. All 18 geometry tests, strict core Clippy and fresh independent correctness review passed.
|
||||
- `23535b4`: accepted desktop route authoring, shared geometry integration, route/label controls, guarded atomic gestures and release-cursor correction. Final independent native review captured clear minimum-size controls with the authored bend/label and the readable lower SA label band. Its full SA view was partly occluded; root's earlier full SA captures provide the complete-view evidence.
|
||||
- Locked workspace tests passed with 196 core, 103 desktop and 22 server tests before the last geometry regressions were added. Final follow-up passed 104 desktop tests, strict full-workspace Clippy and desktop/server builds (`routing-final-*` logs). Independent review also passed four focused desktop tests for the final release-cursor correction, which commits fast drags despite coalesced motion events. Earlier follow-up passed the 1500-edge reproducer and six external preview/commit fixtures. Exact scopes are in release-routing-verification.md; a final full-workspace test rerun after all later edits is not claimed.
|
||||
- Independent stress measurements on 100 nodes/150 edges with eight pins per edge: maximum single-edge preview 16.4 ms debug and 2.4 ms release; settled full solve 863 ms debug and 119 ms release. The optimized settled result slightly exceeds the initial 100 ms target; this remains a measured performance limitation, not a claim that the target passed.
|
||||
- Routing workshop `4b8545d` adds deterministic, validated `.arcadia` and JSON examples plus a reproducible Rust generator. OA and SA architecture views contain three participants and nested work groups; SA includes real functional/component ports, Standard and Flow exchanges, and an internal System exchange for group-movement testing. Generation, source/JSON equality and zero semantic/routing issues were verified.
|
||||
Root operated actual Linux7AC5EEE: first FE drag, Right-to-Bottom port drag, Reset/
|
||||
Undo, repeated Bottom-to-Left drag, source-offscreen arrow pan and completion,
|
||||
Save All/reopen, persisted geometry and source-tree expansion/open. Saved trial:
|
||||
`ui-port-tooltip-linux/project.arcadia`,41objects/27links/0checks. Runtime log empty;
|
||||
Linux window closed normally, exec13766 exit0. Linux was inspected at1440x900;
|
||||
minimum-size acceptance is Windows, not a claim of Linux minimum-size testing.
|
||||
|
||||
## Native checkpoint and evidence boundaries
|
||||
Verification scopes: full485 Windows /488 Linux workspace tests preceded the last
|
||||
pointer/tooltip refinements. Latest main Windows193 desktop tests, strict desktop
|
||||
all-target Clippy and debug build passed. Latest Linux189 desktop tests, strict
|
||||
desktop Clippy and release build passed; four new tooltip lifecycle tests then
|
||||
passed separately. A142-test Linux result from a shared-worktree Cargo cache was
|
||||
identified and EXCLUDED; scoped package cleaning and explicit main recompilation
|
||||
established the valid189-test result. Use a distinct CARGO_TARGET_DIR per worktree.
|
||||
|
||||
The reviewed executable at `ui-routing-reviewed/arcadia-studio.exe` has SHA256 `6DAD490D75F2A67A79A0804F33192EF62A3DCBEA92F5EEDA8EA47788D12273B8`. Root performed default-size OA edge selection without canvas movement, segment drag without a retracing spur, separate label drag with unchanged polyline, displaced-label selection, existing-bend drag, Undo/Redo, Remove bend, Reset routing, and undo restoration. Folding an endpoint container used an automatic promoted edge and disabled route editing; expansion restored the authored pin and label. Model checks remained zero.
|
||||
## Active isolated state integration
|
||||
|
||||
Native Save As and SVG export produced `ui-routing-reviewed/routing-authoring-ui.arcadia` (33,548 bytes) and `.svg` (2,564 bytes). The source contains the authored waypoint and label offset. Root then launched `ui-routing-final/arcadia-studio.exe`, SHA256 `5558CC203E9DAFED3D0BCA1C40B5E4BDE426F00F8BC37DCD9B33A7338ADD5615`, containing `30c7db1`, duplicate fold-notice cleanup and export-dialog copy changes. Native Open reopened the saved source with “All changes saved”, 41 objects, 25 links and zero checks; the bend remained visible and the detached label selected the same edge. Root rendered the actual exported SVG to PNG with Sharp and visually verified the authored detour, label, bounds and nesting.
|
||||
Worktree: `D:/CodexBuilds/Capella2-state-integration`, branch`codex/state-integration`.
|
||||
Target: `D:/CodexBuilds/Capella2-state-integration-target`. Main core is not yet changed.
|
||||
|
||||
The workshop loaded with 12 cards/seven links in OA and 12 cards/12 links in SA; the full model reported 75 objects, 61 links and zero checks. Root dragged the internal Incident decision line to create a pin. Moving one function left that pin fixed; moving the whole System by snapped delta (-20, +40) translated the pin by the same amount. A single Undo/Redo restored both placement and pin state. The typed trial was saved to `ui-routing-final/typed-routing-authoring-ui.arcadia` (66,598 bytes); folding and expanding the System restored the route and the UI reported all changes saved.
|
||||
- `e7a8163` integrates reviewed core state-context commit a63654f, preserving latest
|
||||
anchors and routing labels. State views skip semantic port layout after boundary
|
||||
snapping; both routing and label passes reserve actual internal-row headers.
|
||||
- `2459581` retains behavior drafts until Document commit succeeds.
|
||||
- `53cd096` adds typed state-context forms, placement membership choices and normative
|
||||
source/JSON/REST/OpenAPI contracts. Strict HTML generation passed. Two actual HTTP
|
||||
tests passed, including malformed/invalid rejection, revision/source atomicity and
|
||||
restart. Destination pickers permit intermediate invalid drafts so coordinated
|
||||
element/diagram retargeting is reachable; Apply remains strict.
|
||||
- `e5660b8` integrates App dirty/Close/Save/navigation/mutation guards. Exact prepared
|
||||
commands acknowledge drafts only after accepted source/model writes. Review found
|
||||
passive viewport events applying properties, queued source controls creating
|
||||
competing drafts and stale delete confirmations; all three fixes have App tests.
|
||||
Six App lifecycle tests passed, including typed source-writeback rejection/retry
|
||||
and one Undo. Clean detached buffers after Undo are intentional; reachable bundle
|
||||
and accepted Document are restored exactly.
|
||||
- Integrated baseline:514 Windows workspace tests (277core,199desktop,38server),
|
||||
strict workspace all-target Clippy passed. This baseline precedes direct gestures;
|
||||
there is no native state-gesture acceptance yet.
|
||||
|
||||
On `ui-routing-labels/arcadia-studio.exe`, SHA256 `4D4C8163EA2A81F2D9A241921571BE3118AE57ECD2987E7088878CBCA9F50536`, native reopen of that typed trial retained the SA custom pin and separated labels. Dragging an automatically displaced label was continuous and Undo worked. This closes the label finding together with the geometry tests and independent review.
|
||||
Ownership: root owns App/behavior toolbar/context integration. drawing_correctness
|
||||
owns only new behavior/state_edit.rs planners; drawing_linux owns only new
|
||||
behavior/state_canvas.rs rendering/input. They coordinate explicit Context/Event
|
||||
APIs and use ordinary commands/shared geometry. drawing_requirements completed
|
||||
representation work and is idle for independent review. Root exclusively owns
|
||||
native input. Do not edit another worker's files or share Cargo targets.
|
||||
|
||||
The accepted executable at `ui-routing-accepted/arcadia-studio.exe` has SHA256 `E9B662788CC3979F8E883299CAF9B16917498D6F0DEAB62E02D9A6CE5C18AFB2`. At 1100×700 (captured frame 1102×732), a short 29-pixel bend drag and approximately 18-pixel label drag succeeded on the first attempt. The canvas and controls remained stable; SVG dialog copy fitted. Native export produced `minimum-routing-ui.svg`; its PNG rendering was visually inspected for correct route, label and nesting. This later successful trial supersedes the earlier width-only resize attempt. The accepted minimum-size window retains an unsaved demo with those two gestures; preserve it before switching models. The saved typed workshop remains the durable SA fixture.
|
||||
|
||||
Unexpected concurrent arrangement/view changes were separately preserved to `ui-routing-final/workshop-arrangement-preserved.arcadia` (66,434 bytes). A prior icon-only capture did not establish an application failure; subsequent full native captures succeeded. Obtain fresh inventory before further input instead of relying on historical window IDs.
|
||||
|
||||
Original Capella was operated in a disposable workspace. Native creation demonstrated real FE/function ports and explicit component-port allocation. `Format > Line Style > Oblique` followed by a segment drag created an actual bend without changing its Audio Signal/FOP1/FIP1 endpoints. A rectilinear-corner attempt did not move. See release-capella-workflow-benchmark.md; the reference sample was not saved.
|
||||
|
||||
Earlier Studio windows disappeared during concurrent work. Fresh inventory confirmed absence and no matching application-crash event was observed; the earlier unsaved routing trial was not recovered. It is superseded by the explicitly saved reviewed fixture, not retroactively claimed as recovered.
|
||||
|
||||
## Active drawing integration checkpoint
|
||||
|
||||
Meaningful progress continues: direct connection tools, movable per-diagram port anchors, contextual menus and source folders are implemented. Core commits93fd32c (feasibility scaling) and35133de (port anchors) are integrated. Full Windows workspace passed485 tests (264core,185desktop,36server); full Linux passed488 (267core,185desktop,36server). Final ordered-cursor follow-up passed189 desktop tests on both platforms, strict workspace Clippy and rebuilt desktop binaries. Earlier full runs precede those four additional lifecycle regressions. API/port anchor HTTP tests and strict reST generation passed. Detailed scopes and saved fixtures are in release-port-drawing.md and release-context-menus.md.
|
||||
|
||||
Fresh independent correctness review reproduced post-release mouse motion in one native batch creating a port move or exchange after a stationary click. Ordered CursorMoved coordinates are now authoritative for press and release; tests cover both failures, same-batch drags, stationary-source continuity, menu epochs, middle/arrow pan and fresh-context Reset/Draw. Nearest-glyph hit testing fixes incorrect port identity at overview zoom. Port hover shows name, owner and alias in a separate screen-space frame; no label-text overprint. Fresh requirements/architecture review found no further material issue after these fixes and scope-document correction.
|
||||
|
||||
Root operated final Windows binary `ui-port-drawing-final/arcadia-studio.exe`, SHA2569A7FF074296D49A714AD664848170D717832A28964719A903B45ABE100BBAA1F, window328292, exec68098. Fast FE port-to-port drag, first Bottom port drag, repeated Left drag, arrow panning with source retained offscreen, target completion and single Undo passed with0checks. It currently contains the isolated unsaved41object/26link model with Left port anchor and first FE. Native input is EXCLUSIVELY delegated to drawing_requirements for Save/reopen, Standard boundary drawing, Function-card auto endpoints, menu lifecycle and minimum-size acceptance. Root must not issue native input until handoff. Current Linux binary SHA25623CEAE18F53736B9B38A94E4185C45D6639825A3775DEB3FB814938B9CD00387 is built/tested; native follow-up pending.
|
||||
|
||||
Previous46EE7BD9 trial closed normally (exec90275 exit0) after saving its Bottom anchor/FE fixture, reopening the DE6BD100 Left-anchor/FE/Flow-boundary fixture, SVG export and1100x700 inspection. Saved fixtures and precise results are in release-port-drawing.md. Protected user window7210312 was absent after the interrupted turn; root did not close it. If it returns, do not save/reset/close it. Earlier6228978 likewise absent; no recovery claim.
|
||||
|
||||
Parallel release work: drawing_correctness reviews preserved state-core commit a63654f against current anchors/routing. drawing_linux owns behavior draft lifecycle implementation only in a new isolated worktree, excluding app.rs. All broader first-release requirements remain active and incomplete.
|
||||
## Exact next actions
|
||||
|
||||
1. Finish independent native acceptance of the frozen9A7FF074 Windows build, then root verifies the frozen23CEAE18 Linux build. Cursor, pan, nearest-hit and tooltip fixes have passed automated verification and root's current native drawing/port/pan workflow. Preserve exact binary scopes while broader implementation continues.
|
||||
2. Finish direct-drawing acceptance: default/minimum-size Windows and Linux, existing-port FE and Function-card auto endpoints, Flow/Standard boundary links, invalid/cancelled/folded targets, Save/reopen and SVG. Record exact scopes in release-port-drawing.md, update menu/source-tree acceptance and commit the coherent UX milestone.
|
||||
3. Integrate preserved state-core commit `a63654f` from isolated worktree only after this user-directed usability milestone. Implement direct state/scenario/process gestures, R3 semantic drift and reviewed reconciliation, R6 data contracts, persistent coverage/filters, Home/recent/recovery, hosted ETag workflows, offline guidance and normative contracts. All remain required release work.
|
||||
4. Complete independent requirements, correctness, native UI/UX and architecture reviews for the entire release; address material findings. Verify current Windows/Linux/MSRV builds, runtime workflows, documentation, packages and checksums before completing the broad goal.
|
||||
## Environment and reproducibility
|
||||
1. Commit the verified main tooltip follow-up and evidence, retaining source/GUI/API
|
||||
parity. Latest Windows trial is saved; no final-release claim.
|
||||
2. Integrate state-edit planners and actual persisted canvas with explicit retained
|
||||
behavior view, creation in a region, movement, transition drawing/reconnection,
|
||||
guarded forms, discoverable missing placements, pan/zoom and contextual actions.
|
||||
Build/run/test native at default/minimum sizes; review/reproduce/fix findings.
|
||||
3. Continue direct scenario/process gestures, R3 semantic drift/reconciliation,
|
||||
R6 data contracts, persistent coverage/filters, Home/recent/recovery, hosted ETag
|
||||
workflows, offline guidance and normative contracts. All remain release work.
|
||||
4. Fresh final requirements/domain/correctness/native UX/architecture reviews;
|
||||
Windows/Linux/MSRV checks, actual runtime, docs and packages/checksums before
|
||||
completing the broad goal. V2 or a subsystem checkpoint is insufficient.
|
||||
|
||||
Windows Rust 1.98.1; `CARGO_TARGET_DIR=D:/CodexBuilds/Capella2-01a06e2e`. Release logs and native fixtures are under `D:/CodexBuilds/Capella2-release1-01a06e2e`. Use `cargo test --locked --workspace`, `cargo clippy --locked --workspace --all-targets -- -D warnings`, and `cargo build --locked -p oa-desktop -p oa-server`. Generate the routing example with `cargo run --locked -p oa-core --example routing_workshop`; historical migration goldens stay frozen.
|
||||
## Native safety and environment
|
||||
|
||||
Prior WSL Ubuntu 24.04 evidence is in verification-v2-linux.md; current routing automated/build evidence is in release-routing-linux.md. The Linux routing application was launched with the documented Mesa Vulkan software adapter and operated through Computer Use. Full first-release Linux runtime/package acceptance is still required after remaining implementation. There is no current disk blocker. Do not retry the earlier rejected recursive target deletion. No usage reset or remote push is authorized.
|
||||
Root owns native input. Final Windows1EEBDC3C window2100032/exec55548 is saved on
|
||||
its isolated41/26 trial. Earlier windows524634 and328292 are saved on the Standard
|
||||
and auto-port review fixtures. Re-inventory and inspect current dirty state before
|
||||
operating any window. Protected user7210312 and earlier6228978 were absent; root did
|
||||
not close them and makes no recovery claim. If either returns, do not save/reset/close.
|
||||
|
||||
Main Windows target `D:/CodexBuilds/Capella2-01a06e2e`; Rust1.98.1. Use `cargo test
|
||||
--locked --workspace`, `cargo clippy --locked --workspace --all-targets -- -D warnings`
|
||||
and `cargo build --locked -p oa-desktop -p oa-server`. WSL Ubuntu24.04 uses the
|
||||
existing target/linux-cargo.toml vendor config and its own linux-target; launch
|
||||
with WGPU_BACKEND=vulkan and the Mesa lvp ICD. Release evidence lives under
|
||||
`D:/CodexBuilds/Capella2-release1-01a06e2e`. No remote push or usage reset is authorized.
|
||||
Do not retry the previously rejected broad recursive target deletion.
|
||||
|
||||
@@ -55,4 +55,12 @@ Accept native per-file editing, safe project saves and exact source Undo, then e
|
||||
|
||||
Meaningful progress now includes verified drag and typed-port authoring, accepted editable routing with native save/reopen, group movement and minimum-size evidence, and tested source-bundle/nested-writeback foundations with independent limitations exposed. Production source and direct behavior usability remain open engineering tasks; feature counts alone do not establish completion.
|
||||
|
||||
Current user-directed drawing evidence: palette creation and draggable per-placement port anchors passed scoped native Windows trials with Save/reopen; full485 Windows and488 Linux workspace suites passed before final pointer-release and hover refinements. Fresh independent review exposed post-release motion turning clicks into edits, nearest-port mispicking at overview zoom, and missing target identity feedback. The first two have production regressions and fixes; named owner/alias hover details and source-preserving pan are implemented, with final native acceptance pending. See release-port-drawing.md. The preceding goal turn made concrete progress through implementation, saved source/SVG artifacts, actual runtime verification and reproduced findings; it was not a wait or no-progress turn. Direct behavior and the broader release requirements remain active.
|
||||
Current user-directed drawing evidence: palette creation and draggable per-placement port anchors passed scoped native Windows trials with Save/reopen; full485 Windows and488 Linux workspace suites passed before final pointer-release and hover refinements. Fresh independent review exposed post-release motion turning clicks into edits, nearest-port mispicking at overview zoom, and missing target identity feedback. The first two have production regressions and fixes; named owner/alias hover details and source-preserving pan are implemented, with final native acceptance pending. See release-port-drawing.md. The preceding goal turn made concrete progress through implementation, saved source/SVG artifacts, actual runtime verification and reproduced findings; it was not a wait or no-progress turn. Direct behavior and the broader release requirements remain active.
|
||||
2026-09-06 follow-up: direct drawing, movable ports, menus and source folders now
|
||||
have scoped native Windows/Linux acceptance. Independent QA falsified the initial
|
||||
separate-Frame tooltip fix; a real stacked GPU layer passed native retest. Current
|
||||
main Windows193 desktop tests and Linux189+4 focused tests passed. Independent
|
||||
state/representation/lifecycle integration passed514 Windows workspace tests and
|
||||
strict Clippy in its isolated checkout. Direct state-canvas authoring is underway;
|
||||
all broader release requirements remain active. This turn made concrete implementation,
|
||||
review and runtime progress, not a blocked or waiting-only turn. See STATE.md.
|
||||
|
||||
@@ -41,7 +41,7 @@ Properties supplies the name and contract editing workflow.
|
||||
- Port labels use a separate screen-space frame, avoiding text overprint and
|
||||
keeping target identification legible while zoomed out.
|
||||
|
||||
## Observed verification and remaining acceptance
|
||||
## Earlier verification (superseded by final acceptance below)
|
||||
|
||||
Full Windows workspace passed485 tests (264 core,185 desktop,36 server); full
|
||||
Linux passed488 (267 core,185 desktop,36 server), with strict Linux workspace
|
||||
@@ -81,3 +81,32 @@ tests and strict workspace Clippy but still needs native verification.
|
||||
Pending: final menu lifecycle, Function-card auto endpoint creation, Standard
|
||||
boundary drawing, minimum layout, save/reopen and Linux native workflow.
|
||||
The broader first-release objective remains incomplete.
|
||||
|
||||
## Final tooltip and native acceptance
|
||||
|
||||
The earlier statement that separate Frames eliminated overprint was falsified by
|
||||
independent native QA. Iced batches text after meshes within one GPU layer. A
|
||||
passive second Canvas in Stack now creates a real layer above diagram text, with
|
||||
no input capture or cursor override. Context-scoped held-button tracking prevents
|
||||
stale suppression after menu dismissal and premature tooltips during leave/reentry.
|
||||
Four production lifecycle tests passed on Windows and Linux.
|
||||
|
||||
Final Windows193 desktop tests, strict desktop Clippy and build passed. Root tested
|
||||
binary1EEBDC3C (full SHA256 in ui-port-tooltip-final executable): first Bottom drag,
|
||||
menu outside dismissal, first repeated Left drag, FE creation and Save,41/26/0.
|
||||
Independent9A7/3F534C review passed Standard rejection/completion, function-card
|
||||
endpoint generation, one Undo/Redo, Save/reopen and minimum1100x700; it reproduced
|
||||
then verified the tooltip fix. Exact report: drawing-independent-native-review.md
|
||||
in the external evidence directory.
|
||||
|
||||
Root operated Linux binary7AC5EEEFFFD5514C771CF0E3B75471CA771DF75BE5DEBE9B9928B1527E1591F1:
|
||||
first FE drag; Right→Bottom and Bottom→Left port movement; Reset/Undo; arrow pan
|
||||
with source offscreen and target completion; Save/reopen; source folders and file
|
||||
opening. Saved ui-port-tooltip-linux/project.arcadia,41/27/0, contains both exchanges
|
||||
and Left anchor. Runtime log empty; normal close exit0. Inspected1440x900; minimum
|
||||
layout evidence is Windows. Linux189 desktop tests/strict Clippy/release passed,
|
||||
then four new lifecycle tests passed separately. A stale142-test shared-worktree
|
||||
cache result was excluded and main explicitly rebuilt; targets must be checkout-specific.
|
||||
|
||||
Drawing milestone accepted with these evidence boundaries. The broader first
|
||||
release and direct behavior editing remain incomplete.
|
||||
|
||||
Reference in New Issue
Block a user