Stage explicit prerequisite sources inside behavior creation forms
This commit is contained in:
@@ -34,6 +34,11 @@ harness/behavior-creation-contract.rs -text whitespace=cr-at-eol
|
||||
harness/experiments/source-cli-independent-20260911/** -text whitespace=cr-at-eol
|
||||
harness/experiments/authoring-prerelease-20260911/** -text whitespace=cr-at-eol
|
||||
harness/experiments/cli-packaging-20260911/** -text whitespace=cr-at-eol
|
||||
harness/experiments/cli-prerelease-20260911/** -text whitespace=cr-at-eol
|
||||
harness/experiments/contextual-source-20260911/** -text whitespace=cr-at-eol
|
||||
harness/experiments/contextual-source-20260911/**/*.log whitespace=-blank-at-eof,cr-at-eol
|
||||
harness/fixtures/staged-source-authoring/** -text whitespace=cr-at-eol
|
||||
harness/staged-source-authoring-contract.rs -text whitespace=cr-at-eol
|
||||
|
||||
# Preserve checksum-bound font notices verbatim through Git round trips.
|
||||
scripts/windows-notices/GNOME-Cantarell-61362600e104-COPYING -text
|
||||
|
||||
@@ -854,8 +854,12 @@ impl App {
|
||||
let scenario_selection = self
|
||||
.behavior
|
||||
.scenario
|
||||
.created_selection(&command)
|
||||
.or_else(|| self.behavior.topology.created_selection(&command));
|
||||
.created_selection(self.project(), &command)
|
||||
.or_else(|| {
|
||||
self.behavior
|
||||
.topology
|
||||
.created_selection(self.project(), &command)
|
||||
});
|
||||
match self.document.execute(command) {
|
||||
Ok(selected) => {
|
||||
if let Some(created) = created {
|
||||
@@ -1031,8 +1035,10 @@ impl App {
|
||||
window::close_requests().map(|id| Message::Request(Pending::Close(id))),
|
||||
window::resize_events().map(|(_, size)| Message::WindowResized(size)),
|
||||
architecture_authoring::subscription(self),
|
||||
behavior::creation::subscription(self.behavior.creation.has_pending())
|
||||
.map(|()| Message::Escape),
|
||||
behavior::creation::subscription(
|
||||
self.behavior.creation.has_pending() || self.behavior.source_active(),
|
||||
)
|
||||
.map(|()| Message::Escape),
|
||||
iced::event::listen_with(|event, status, _| {
|
||||
let iced::Event::Keyboard(keyboard::Event::KeyPressed {
|
||||
key,
|
||||
@@ -1519,6 +1525,37 @@ impl App {
|
||||
return Task::none();
|
||||
}
|
||||
match mutation {
|
||||
CanvasEvent::First(_, tool) => {
|
||||
let empty = match tool {
|
||||
scenario::Tool::Lifeline => !self
|
||||
.project()
|
||||
.children(context.scenario)
|
||||
.any(|e| e.kind() == Kind::Lifeline),
|
||||
scenario::Tool::Message | scenario::Tool::Action => {
|
||||
self.project()
|
||||
.children(context.scenario)
|
||||
.any(|e| e.kind() == Kind::Lifeline)
|
||||
&& !self
|
||||
.project()
|
||||
.children(context.scenario)
|
||||
.any(|e| e.kind() == Kind::Occurrence)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if !empty {
|
||||
self.status="This scenario already has content. Use its current authoring tools.".into();
|
||||
return Task::none();
|
||||
}
|
||||
let mut state = std::mem::take(&mut self.behavior.scenario);
|
||||
let result = state.update(
|
||||
self.project(),
|
||||
scenario::Event::Start(context.scenario, tool),
|
||||
);
|
||||
self.behavior.scenario = state;
|
||||
if let Err(error) = result {
|
||||
self.status = error;
|
||||
}
|
||||
}
|
||||
CanvasEvent::BeginOccurrence {
|
||||
tool,
|
||||
slot,
|
||||
@@ -1754,7 +1791,15 @@ impl App {
|
||||
return self.update(Message::Add(child));
|
||||
}
|
||||
Message::Escape => {
|
||||
if self.behavior.creation.has_pending() {
|
||||
if self.behavior.source_back() {
|
||||
self.status =
|
||||
"Returned to the unchanged parent form; no source was created.".into();
|
||||
return Task::none();
|
||||
}
|
||||
if self.behavior.source_active() {
|
||||
self.behavior.acknowledge_commit();
|
||||
self.status = "Behavior form cancelled; no staged source was created.".into();
|
||||
} else if self.behavior.creation.has_pending() {
|
||||
self.behavior.creation.acknowledge_commit();
|
||||
self.status = "Behavior creation cancelled".into();
|
||||
}
|
||||
@@ -2321,10 +2366,13 @@ impl App {
|
||||
self.status = "Apply or cancel the current draft before starting a new behavior. Your inputs are retained.".into();
|
||||
return Task::none();
|
||||
}
|
||||
if !creating && event.starts_form() && !self.behavior.has_pending() && !self.apply()
|
||||
if (event.starts_form() || (event.is_source() && !event.is_source_back()))
|
||||
&& (self.source_dirty() || self.draft_dirty())
|
||||
{
|
||||
self.status="Apply or cancel the other editors before starting this form. Your inputs are retained.".into();
|
||||
return Task::none();
|
||||
}
|
||||
let source_was_open = self.behavior.source_open();
|
||||
if event.is_submit() && (self.source_dirty() || self.draft_dirty()) {
|
||||
self.status = "Revert the other drafts before applying the behavior form. Your inputs are retained.".into();
|
||||
return Task::none();
|
||||
@@ -2342,6 +2390,11 @@ impl App {
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
if !source_was_open && self.behavior.source_open() {
|
||||
return iced::widget::operation::focus(
|
||||
behavior::source_draft::NAME_INPUT,
|
||||
);
|
||||
}
|
||||
if focus_name {
|
||||
return iced::widget::operation::focus(behavior::creation::NAME_INPUT);
|
||||
}
|
||||
@@ -2537,13 +2590,19 @@ impl App {
|
||||
Message::Undo | Message::Redo => {
|
||||
let redo = matches!(message, Message::Redo);
|
||||
if self.apply() {
|
||||
if redo {
|
||||
self.document.redo();
|
||||
let changed = if redo {
|
||||
self.document.redo()
|
||||
} else {
|
||||
self.document.undo();
|
||||
self.document.undo()
|
||||
};
|
||||
if changed {
|
||||
self.sync();
|
||||
}
|
||||
self.sync();
|
||||
self.status = if redo {
|
||||
self.status = if !changed && redo {
|
||||
"Nothing to redo"
|
||||
} else if !changed {
|
||||
"Nothing to undo"
|
||||
} else if redo {
|
||||
"Model change redone"
|
||||
} else {
|
||||
"Model change undone"
|
||||
|
||||
@@ -214,6 +214,11 @@ impl App {
|
||||
.is_some_and(architecture_authoring::State::inline)
|
||||
{
|
||||
Task::batch([lint, iced::widget::operation::focus("architecture-name")])
|
||||
} else if self.page == Page::Behavior && self.behavior.source_open() {
|
||||
Task::batch([
|
||||
lint,
|
||||
iced::widget::operation::focus(behavior::source_draft::NAME_INPUT),
|
||||
])
|
||||
} else if self.page == Page::Behavior && self.behavior.creation.created().is_some() {
|
||||
Task::batch([
|
||||
lint,
|
||||
|
||||
@@ -14,8 +14,11 @@ use iced::{
|
||||
};
|
||||
use oa_core::*;
|
||||
use std::collections::BTreeMap;
|
||||
#[cfg(test)]
|
||||
mod contextual_source_tests;
|
||||
pub(crate) mod creation;
|
||||
pub(crate) mod scenario;
|
||||
pub(crate) mod source_draft;
|
||||
pub(crate) mod state_canvas;
|
||||
pub(crate) mod state_edit;
|
||||
pub(crate) mod state_menu;
|
||||
@@ -739,6 +742,29 @@ pub enum Event {
|
||||
Submit,
|
||||
}
|
||||
impl Event {
|
||||
pub fn is_source_back(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Creation(creation::Event::Source(source_draft::Event::Edit(
|
||||
_,
|
||||
source_draft::Edit::Back
|
||||
))) | Self::Scenario(scenario::Event::Source(source_draft::Event::Edit(
|
||||
_,
|
||||
source_draft::Edit::Back
|
||||
))) | Self::Topology(topology::Event::Source(source_draft::Event::Edit(
|
||||
_,
|
||||
source_draft::Edit::Back
|
||||
)))
|
||||
)
|
||||
}
|
||||
pub fn is_source(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Creation(creation::Event::Source(_))
|
||||
| Self::Scenario(scenario::Event::Source(_))
|
||||
| Self::Topology(topology::Event::Source(_))
|
||||
)
|
||||
}
|
||||
pub fn starts_form(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
@@ -869,6 +895,18 @@ impl State {
|
||||
|
||||
/// Clear the active form after its prepared command commits successfully.
|
||||
/// Rejected commands must leave the form available for repair and retry.
|
||||
pub fn source_active(&self) -> bool {
|
||||
self.creation.source_active()
|
||||
|| self.scenario.source_active()
|
||||
|| self.topology.source_active()
|
||||
}
|
||||
pub fn source_open(&self) -> bool {
|
||||
self.creation.source_open() || self.scenario.source_open() || self.topology.source_open()
|
||||
}
|
||||
pub fn source_back(&mut self) -> bool {
|
||||
self.creation.source_back() || self.scenario.source_back() || self.topology.source_back()
|
||||
}
|
||||
|
||||
pub fn acknowledge_commit(&mut self) {
|
||||
self.creation.acknowledge_commit();
|
||||
self.topology.acknowledge_commit();
|
||||
@@ -916,6 +954,40 @@ pub fn view(app: &App) -> Element<'_, Message> {
|
||||
if let Some(card) = app.behavior.creation.view(p) {
|
||||
return card.map(|event| Message::Behavior(Event::Creation(event)));
|
||||
}
|
||||
if let Some(owner) = app.behavior.pending_owner() {
|
||||
let kind = p.elements.get(&owner).map(oa_core::Element::kind);
|
||||
let unavailable = p.layer_of(owner) != Some(app.layer)
|
||||
|| (app.behavior.scenario.pending_owner().is_some() && kind != Some(Kind::Scenario))
|
||||
|| (app.behavior.topology.pending_owner().is_some()
|
||||
&& !matches!(kind, Some(Kind::Process | Kind::FunctionalChain)));
|
||||
if unavailable {
|
||||
let mut out=column![text("The pending behavior owner is unavailable").size(20),text("Your inputs are retained. Return from the source form or cancel this parent draft before choosing another behavior.").size(13)].spacing(12);
|
||||
if let Some(name) = app
|
||||
.behavior
|
||||
.scenario
|
||||
.pending_name()
|
||||
.or_else(|| app.behavior.topology.pending_name())
|
||||
{
|
||||
out =
|
||||
out.push(text(format!("Pending consumer name: {}", short(name, 80))).size(14));
|
||||
}
|
||||
if let Some(child) = app.behavior.scenario.source_view(p) {
|
||||
out = out.push(child.map(|e| Message::Behavior(Event::Scenario(e))));
|
||||
} else if let Some(child) = app.behavior.topology.source_view(p) {
|
||||
out = out.push(child.map(|e| Message::Behavior(Event::Topology(e))));
|
||||
} else {
|
||||
let cancel = if app.behavior.scenario.pending_owner().is_some() {
|
||||
Event::Scenario(scenario::Event::Cancel)
|
||||
} else if app.behavior.topology.pending_owner().is_some() {
|
||||
Event::Topology(topology::Event::Cancel)
|
||||
} else {
|
||||
Event::States(states::Event::Cancel)
|
||||
};
|
||||
out = out.push(button("Cancel retained draft").on_press(Message::Behavior(cancel)));
|
||||
}
|
||||
return container(out).padding(16).width(Fill).height(Fill).into();
|
||||
}
|
||||
}
|
||||
let choices = p
|
||||
.elements
|
||||
.values()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -75,6 +75,7 @@ impl Picker {
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Source(super::source_draft::Event),
|
||||
Open(Layer),
|
||||
Choose(Family),
|
||||
Name(String),
|
||||
@@ -97,6 +98,11 @@ struct Browser {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Draft {
|
||||
#[serde(default)]
|
||||
source: super::source_draft::State,
|
||||
#[serde(default = "Id::new_v4")]
|
||||
invocation: Id,
|
||||
|
||||
version: u32,
|
||||
document: Id,
|
||||
layer: Layer,
|
||||
@@ -125,6 +131,17 @@ pub struct Created {
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn source_active(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.engaged())
|
||||
}
|
||||
|
||||
pub fn source_open(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.is_open())
|
||||
}
|
||||
pub fn source_back(&mut self) -> bool {
|
||||
self.draft.as_mut().is_some_and(|d| d.source.back())
|
||||
}
|
||||
|
||||
pub fn has_pending(&self) -> bool {
|
||||
self.draft.is_some()
|
||||
}
|
||||
@@ -174,6 +191,49 @@ impl State {
|
||||
.command(p)
|
||||
}
|
||||
pub fn update(&mut self, p: &Project, event: Event) -> Result<Option<Command>, String> {
|
||||
if let Event::Source(event) = event {
|
||||
if self
|
||||
.draft
|
||||
.as_mut()
|
||||
.ok_or("Start the consumer form first.")?
|
||||
.source
|
||||
.dismiss(&event)?
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
let d = self
|
||||
.draft
|
||||
.as_ref()
|
||||
.ok_or("Start the consumer form first.")?;
|
||||
if d.family != Some(Family::Machine) {
|
||||
return Err("This reference does not support staged source creation.".into());
|
||||
}
|
||||
if d.document != p.id {
|
||||
return Err("This behavior draft belongs to another document.".into());
|
||||
}
|
||||
let mut next = d.clone();
|
||||
if let Some(id) = next.source.update(
|
||||
p,
|
||||
super::source_draft::Scope::Machine { layer: d.layer },
|
||||
d.invocation,
|
||||
event,
|
||||
)? {
|
||||
next.owner = Some(id);
|
||||
let preview = next
|
||||
.source
|
||||
.preview(p, next.owner)?
|
||||
.ok_or("New owner preview is missing.")?;
|
||||
if !eligible(&preview, next.layer, Picker::Owner, id) {
|
||||
return Err("This participant cannot own the machine.".into());
|
||||
}
|
||||
}
|
||||
self.draft = Some(next);
|
||||
return Ok(None);
|
||||
}
|
||||
if self.source_open() && !matches!(&event, Event::Cancel) {
|
||||
return Err("Use the new source or go Back before editing the parent form.".into());
|
||||
}
|
||||
|
||||
match event {
|
||||
Event::Cancel => {
|
||||
self.draft = None;
|
||||
@@ -184,6 +244,8 @@ impl State {
|
||||
return Err("Create or cancel the pending behavior first.".into());
|
||||
}
|
||||
self.draft = Some(Draft {
|
||||
source: Default::default(),
|
||||
invocation: Id::new_v4(),
|
||||
version: 1,
|
||||
document: p.id,
|
||||
layer,
|
||||
@@ -332,7 +394,7 @@ fn reference_context(p: &Project, e: &Element) -> String {
|
||||
};
|
||||
format!("{} · {} · {location}", e.kind(), e.alias)
|
||||
}
|
||||
fn reference_label(p: &Project, id: Id) -> String {
|
||||
pub(super) fn reference_label(p: &Project, id: Id) -> String {
|
||||
p.elements
|
||||
.get(&id)
|
||||
.map(|e| format!("{} · {}", e.name, reference_context(p, e)))
|
||||
@@ -340,6 +402,15 @@ fn reference_label(p: &Project, id: Id) -> String {
|
||||
}
|
||||
impl Draft {
|
||||
fn command(&self, p: &Project) -> Result<Command, String> {
|
||||
self.source.check_scope(
|
||||
super::source_draft::Scope::Machine { layer: self.layer },
|
||||
self.owner,
|
||||
)?;
|
||||
let preview = self.source.preview(p, self.owner)?;
|
||||
let command = self.consumer_command(preview.as_ref().unwrap_or(p))?;
|
||||
self.source.combine(p, self.owner, command)
|
||||
}
|
||||
fn consumer_command(&self, p: &Project) -> Result<Command, String> {
|
||||
if self.document != p.id {
|
||||
return Err("This draft belongs to another document.".into());
|
||||
}
|
||||
@@ -475,6 +546,21 @@ impl State {
|
||||
p: &'a Project,
|
||||
) -> Option<UiElement<'a, Event, iced::Theme, R>> {
|
||||
let d = self.draft.as_ref()?;
|
||||
if let Some(view) = d.source.view(p) {
|
||||
return Some(
|
||||
column![
|
||||
text(format!(
|
||||
"State machine name: {}",
|
||||
crate::views::short(&d.name, 60)
|
||||
))
|
||||
.size(12),
|
||||
view.map(Event::Source)
|
||||
]
|
||||
.spacing(6)
|
||||
.height(Fill)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
let mut fields = column![].spacing(10);
|
||||
let title = if let Some(family) = d.family {
|
||||
fields = fields.push(
|
||||
@@ -488,7 +574,7 @@ impl State {
|
||||
Family::Sequence => {
|
||||
fields = fields.push(
|
||||
text(format!(
|
||||
"Owned by the {} layer root. Involve existing work after creation.",
|
||||
"Owned by the {} layer root. Add work and exchange contributions after creation.",
|
||||
d.layer
|
||||
))
|
||||
.size(12),
|
||||
@@ -531,7 +617,17 @@ impl State {
|
||||
}
|
||||
}
|
||||
Family::Machine => {
|
||||
if let Some(label) = d.source.label(d.owner) {
|
||||
fields = fields.push(text(label).size(13)).push(text("Create and open commits the new owner and machine together, including the first view only when selected.").size(12));
|
||||
}
|
||||
fields = fields.push(picker_view(p, d, Picker::Owner));
|
||||
fields = fields.push(
|
||||
button("Create new owner…")
|
||||
.on_press(Event::Source(super::source_draft::Event::Open(
|
||||
d.invocation,
|
||||
)))
|
||||
.padding(7),
|
||||
);
|
||||
fields = fields.push(
|
||||
checkbox(d.first_view)
|
||||
.label("Create the first state view")
|
||||
@@ -544,9 +640,9 @@ impl State {
|
||||
} else {
|
||||
for family in [Family::Sequence, Family::Scenario, Family::Machine] {
|
||||
let purpose = match family {
|
||||
Family::Sequence => "A path through existing work and exchanges",
|
||||
Family::Sequence => "A path through work and exchanges",
|
||||
Family::Scenario => "Ordered interactions from an explicit viewpoint",
|
||||
Family::Machine => "States and modes of an existing participant",
|
||||
Family::Machine => "States and modes of an explicitly chosen participant",
|
||||
};
|
||||
fields = fields.push(
|
||||
button(
|
||||
@@ -616,7 +712,7 @@ fn picker_view<'a, R: iced::advanced::text::Renderer + 'a>(
|
||||
}
|
||||
if options.is_empty() {
|
||||
out = out.push(text(match picker {
|
||||
Picker::Owner => "No matching participant. Refine the search, or cancel and create a participant in Architecture first.",
|
||||
Picker::Owner => "No matching participant. Refine the search or choose Create new owner.",
|
||||
Picker::Context => "No matching context. Refine the search, or leave this optional reference empty.",
|
||||
}).size(12));
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@ impl std::fmt::Display for CanvasTool {
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CanvasEvent {
|
||||
First(Context, Tool),
|
||||
Scrolled(Context, ScrollArea, iced::Vector),
|
||||
Restored(Context, Id, ScrollArea, iced::Vector),
|
||||
Viewport(Context, Size),
|
||||
@@ -132,7 +133,8 @@ pub enum ScrollArea {
|
||||
impl CanvasEvent {
|
||||
pub fn context(&self) -> Context {
|
||||
match self {
|
||||
Self::Scrolled(context, _, _)
|
||||
Self::First(context, _)
|
||||
| Self::Scrolled(context, _, _)
|
||||
| Self::Restored(context, ..)
|
||||
| Self::Viewport(context, _)
|
||||
| Self::Zoom(context, _)
|
||||
@@ -162,6 +164,7 @@ impl std::fmt::Display for Operator {
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Source(super::source_draft::Event),
|
||||
Start(Id, Tool),
|
||||
Cancel,
|
||||
Submit,
|
||||
@@ -240,6 +243,13 @@ struct CallChoiceContext {
|
||||
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Draft {
|
||||
#[serde(default)]
|
||||
source: super::source_draft::State,
|
||||
#[serde(default = "Id::new_v4")]
|
||||
invocation: Id,
|
||||
#[serde(default)]
|
||||
source_origin: Option<(Id, oa_core::Element)>,
|
||||
|
||||
owner: Id,
|
||||
parent: Id,
|
||||
before: Option<Id>,
|
||||
@@ -272,6 +282,28 @@ struct Draft {
|
||||
choice_page: usize,
|
||||
}
|
||||
impl State {
|
||||
pub(super) fn pending_name(&self) -> Option<&str> {
|
||||
self.draft.as_ref().map(|d| d.name.as_str())
|
||||
}
|
||||
pub(super) fn source_view<'a>(&'a self, p: &'a Project) -> Option<iced::Element<'a, Event>> {
|
||||
self.draft
|
||||
.as_ref()?
|
||||
.source
|
||||
.view(p)
|
||||
.map(|v| v.map(Event::Source))
|
||||
}
|
||||
|
||||
pub fn source_active(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.engaged())
|
||||
}
|
||||
|
||||
pub fn source_open(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.is_open())
|
||||
}
|
||||
pub fn source_back(&mut self) -> bool {
|
||||
self.draft.as_mut().is_some_and(|d| d.source.back())
|
||||
}
|
||||
|
||||
pub(crate) fn enter(&mut self, document: Id, owner: Id) {
|
||||
if self.presentation.identity != Some((document, owner)) {
|
||||
self.presentation = workspace::Presentation {
|
||||
@@ -452,8 +484,16 @@ impl State {
|
||||
}
|
||||
cached.as_ref().unwrap().1.clone()
|
||||
}
|
||||
pub(crate) fn created_selection(&self, command: &Command) -> Option<Id> {
|
||||
pub(crate) fn created_selection(&self, p: &Project, command: &Command) -> Option<Id> {
|
||||
let draft = self.draft.as_ref()?;
|
||||
if self
|
||||
.draft
|
||||
.as_ref()
|
||||
.is_some_and(|d| d.source.label(d.target).is_some())
|
||||
&& self.prepare_pending(p).ok().as_ref() != Some(command)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
fn created(command: &Command, parent: Id) -> Option<Id> {
|
||||
match command {
|
||||
Command::CreateElement(element) if element.parent == Some(parent) => {
|
||||
@@ -568,6 +608,61 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn update(&mut self, p: &Project, event: Event) -> Result<Option<Command>, String> {
|
||||
if let Event::Source(event) = event {
|
||||
if self
|
||||
.draft
|
||||
.as_mut()
|
||||
.ok_or("Start the consumer form first.")?
|
||||
.source
|
||||
.dismiss(&event)?
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
let d = self
|
||||
.draft
|
||||
.as_ref()
|
||||
.ok_or("Start the consumer form first.")?;
|
||||
if d.tool != Tool::Lifeline {
|
||||
return Err("This reference does not support staged source creation.".into());
|
||||
}
|
||||
if d.source_origin.as_ref().is_some_and(|(document, owner)| {
|
||||
*document != p.id || p.elements.get(&d.owner) != Some(owner)
|
||||
}) {
|
||||
return Err("The original consumer changed. Cancel and reopen its form; the current draft is retained.".into());
|
||||
}
|
||||
if d.source_origin.is_none() && d.source.engaged() {
|
||||
return Err("The recovered source draft has no original document binding. Go Back or cancel it.".into());
|
||||
}
|
||||
let mut next = d.clone();
|
||||
if next.source_origin.is_none() && matches!(&event, super::source_draft::Event::Open(_))
|
||||
{
|
||||
next.source_origin = Some((
|
||||
p.id,
|
||||
p.elements
|
||||
.get(&d.owner)
|
||||
.ok_or("The consumer owner no longer exists.")?
|
||||
.clone(),
|
||||
));
|
||||
}
|
||||
if let Some(id) = next.source.update(
|
||||
p,
|
||||
super::source_draft::Scope::Lifeline {
|
||||
owner: d.owner,
|
||||
viewpoint: viewpoint(p, d.owner),
|
||||
},
|
||||
d.invocation,
|
||||
event,
|
||||
)? {
|
||||
next.target = Some(id);
|
||||
next.command(p)?;
|
||||
}
|
||||
self.draft = Some(next);
|
||||
return Ok(None);
|
||||
}
|
||||
if self.source_open() && !matches!(&event, Event::Cancel) {
|
||||
return Err("Use the new source or go Back before editing the parent form.".into());
|
||||
}
|
||||
|
||||
if self.draft.is_some() && matches!(&event, Event::Start(..)) {
|
||||
return Err(PENDING_DRAFT.into());
|
||||
}
|
||||
@@ -577,6 +672,9 @@ impl State {
|
||||
return Err("Choose a scenario.".into());
|
||||
}
|
||||
self.draft = Some(Draft {
|
||||
source: Default::default(),
|
||||
invocation: Id::new_v4(),
|
||||
source_origin: Some((p.id, p.elements[&owner].clone())),
|
||||
owner,
|
||||
parent: owner,
|
||||
before: None,
|
||||
@@ -940,7 +1038,14 @@ fn valid_body_choice(p: &Project, owner: Id, body: OccurrenceBody) -> bool {
|
||||
execute_batch(p, &[Command::CreateElement(e)]).is_ok()
|
||||
}
|
||||
fn sources(p: &Project, d: &Draft) -> Vec<Choice> {
|
||||
let layer = p.elements[&d.owner].layer();
|
||||
let Some(owner) = p
|
||||
.elements
|
||||
.get(&d.owner)
|
||||
.filter(|e| e.kind() == Kind::Scenario)
|
||||
else {
|
||||
return vec![];
|
||||
};
|
||||
let layer = owner.layer();
|
||||
let mut values: Vec<_> = p
|
||||
.elements
|
||||
.values()
|
||||
@@ -1256,6 +1361,28 @@ impl Draft {
|
||||
e
|
||||
}
|
||||
fn command(&self, p: &Project) -> Result<Command, String> {
|
||||
if self.source.engaged()
|
||||
&& self.source_origin.as_ref().is_none_or(|(document, owner)| {
|
||||
*document != p.id || p.elements.get(&self.owner) != Some(owner)
|
||||
})
|
||||
{
|
||||
return Err("The original consumer document or owner changed. Cancel and reopen its form; your draft is retained.".into());
|
||||
}
|
||||
self.source.check_scope(
|
||||
super::source_draft::Scope::Lifeline {
|
||||
owner: self.owner,
|
||||
viewpoint: viewpoint(p, self.owner),
|
||||
},
|
||||
self.target,
|
||||
)?;
|
||||
let preview = self.source.preview(p, self.target)?;
|
||||
let command = self.consumer_command(preview.as_ref().unwrap_or(p))?;
|
||||
self.source.combine(p, self.target, command)
|
||||
}
|
||||
fn consumer_command(&self, p: &Project) -> Result<Command, String> {
|
||||
if p.elements.get(&self.owner).map(oa_core::Element::kind) != Some(Kind::Scenario) {
|
||||
return Err("The scenario no longer exists. Cancel or restore its owner.".into());
|
||||
}
|
||||
if !parents(p, self.owner).iter().any(|c| c.id == self.parent) {
|
||||
return Err("Choose this scenario or one of its operands as destination.".into());
|
||||
}
|
||||
@@ -1266,6 +1393,8 @@ impl Draft {
|
||||
.unwrap_or(self.tool.label());
|
||||
let name = if self.name.trim().is_empty() {
|
||||
default
|
||||
} else if self.source.label(self.target).is_some() {
|
||||
self.name.as_str()
|
||||
} else {
|
||||
self.name.trim()
|
||||
};
|
||||
|
||||
@@ -168,6 +168,11 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
|
||||
.wrap(),
|
||||
text(if pending {
|
||||
"Pending form · the highlighted sequence position is retained".to_owned()
|
||||
} else if !p.children(owner).any(|e| e.kind() == Kind::Lifeline) {
|
||||
"Start with a lifeline representing existing or explicitly new work / participants."
|
||||
.into()
|
||||
} else if !p.children(owner).any(|e| e.kind() == Kind::Occurrence) {
|
||||
"Choose a first message, action or another tool; no occurrence is selected yet.".into()
|
||||
} else {
|
||||
let guidance = match tool {
|
||||
CanvasTool::Message(_) => {
|
||||
@@ -186,6 +191,32 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
|
||||
.size(11)
|
||||
]
|
||||
.spacing(6);
|
||||
if !pending {
|
||||
if !p.children(owner).any(|e| e.kind() == Kind::Lifeline) {
|
||||
header = header.push(
|
||||
row![
|
||||
text(format!("No lifelines · {:?}", viewpoint(p, owner))).size(12),
|
||||
button("Add first lifeline").on_press_maybe(clean.then_some({
|
||||
Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Lifeline))
|
||||
}))
|
||||
]
|
||||
.spacing(8),
|
||||
);
|
||||
} else if !p.children(owner).any(|e| e.kind() == Kind::Occurrence) {
|
||||
header = header.push(
|
||||
row![
|
||||
text("No occurrences yet").size(12),
|
||||
button("Add first message").on_press_maybe(clean.then_some({
|
||||
Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Message))
|
||||
})),
|
||||
button("Add first action").on_press_maybe(clean.then_some({
|
||||
Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Action))
|
||||
}))
|
||||
]
|
||||
.spacing(8),
|
||||
);
|
||||
}
|
||||
}
|
||||
if limited {
|
||||
header = header
|
||||
.push(text("Minimum zoom reached · scroll to see the remaining scenario.").size(11));
|
||||
@@ -295,272 +326,301 @@ pub fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Element<'a
|
||||
.as_ref()
|
||||
.filter(|d| d.owner == owner)
|
||||
{
|
||||
let mut form = column![
|
||||
text(d.tool.label()).size(16),
|
||||
text_input("Name (defaults to selected source)", &d.name)
|
||||
.on_input(|s| event(Event::Name(s)))
|
||||
.padding(9)
|
||||
.size(12)
|
||||
]
|
||||
.spacing(9);
|
||||
if d.tool != Tool::Lifeline {
|
||||
form = form.push(label(format!(
|
||||
"Insert: {}",
|
||||
slot_label(
|
||||
p,
|
||||
Slot {
|
||||
parent: d.parent,
|
||||
before: d.before
|
||||
}
|
||||
)
|
||||
)));
|
||||
if d.before.is_some() {
|
||||
form = form.push(
|
||||
button("Append to this sequence instead").on_press(event(Event::AppendInstead)),
|
||||
);
|
||||
}
|
||||
form = form.push(picker(
|
||||
parents(p, owner),
|
||||
Some(d.parent),
|
||||
"Destination sequence / operand…",
|
||||
Event::Parent,
|
||||
));
|
||||
}
|
||||
if matches!(
|
||||
d.tool,
|
||||
Tool::Lifeline | Tool::Reuse | Tool::Action | Tool::Observation
|
||||
) {
|
||||
form = form.push(picker(
|
||||
sources(p, d),
|
||||
d.target,
|
||||
"Choose a named source…",
|
||||
Event::Target,
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Message {
|
||||
form = form.push(
|
||||
pick_list(
|
||||
vec![
|
||||
MessageStyle::Asynchronous,
|
||||
MessageStyle::Call,
|
||||
MessageStyle::CallReply,
|
||||
MessageStyle::Reply,
|
||||
MessageStyle::Create,
|
||||
MessageStyle::Delete,
|
||||
MessageStyle::Timer,
|
||||
],
|
||||
Some(d.style),
|
||||
|style| event(Event::Style(style)),
|
||||
)
|
||||
.width(Fill)
|
||||
.padding(9)
|
||||
.text_size(12),
|
||||
);
|
||||
if d.style == MessageStyle::Reply {
|
||||
form = form.push(bounded_picker(
|
||||
app.behavior.scenario.call_choices(p, context, d),
|
||||
d,
|
||||
d.call,
|
||||
"Choose the earlier call…",
|
||||
Event::Call,
|
||||
if let Some(child) = d.source.view(p) {
|
||||
form_panel = column![
|
||||
text(format!(
|
||||
"Consumer name: {}",
|
||||
crate::views::short(&d.name, 60)
|
||||
))
|
||||
.size(12),
|
||||
child.map(|e| event(Event::Source(e)))
|
||||
]
|
||||
.spacing(6)
|
||||
.height(Fill)
|
||||
.into();
|
||||
} else {
|
||||
let mut form = column![
|
||||
text(d.tool.label()).size(16),
|
||||
text_input("Name (defaults to selected source)", &d.name)
|
||||
.on_input(|s| event(Event::Name(s)))
|
||||
.padding(9)
|
||||
.size(12)
|
||||
]
|
||||
.spacing(9);
|
||||
if d.tool != Tool::Lifeline {
|
||||
form = form.push(label(format!(
|
||||
"Insert: {}",
|
||||
slot_label(
|
||||
p,
|
||||
Slot {
|
||||
parent: d.parent,
|
||||
before: d.before
|
||||
}
|
||||
)
|
||||
)));
|
||||
if d.before.is_some() {
|
||||
form = form.push(
|
||||
button("Append to this sequence instead")
|
||||
.on_press(event(Event::AppendInstead)),
|
||||
);
|
||||
}
|
||||
form = form.push(picker(
|
||||
parents(p, owner),
|
||||
Some(d.parent),
|
||||
"Destination sequence / operand…",
|
||||
Event::Parent,
|
||||
));
|
||||
if d.call.is_some() {
|
||||
form = form.push(label(
|
||||
}
|
||||
if matches!(
|
||||
d.tool,
|
||||
Tool::Lifeline | Tool::Reuse | Tool::Action | Tool::Observation
|
||||
) {
|
||||
form = form.push(picker(
|
||||
sources(p, d),
|
||||
d.target,
|
||||
"Choose a named source…",
|
||||
Event::Target,
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Lifeline {
|
||||
if let Some(title) = d.source.label(d.target) {
|
||||
form = form.push(label(title)).push(label(
|
||||
"Create commits one new source and this lifeline together.",
|
||||
));
|
||||
}
|
||||
if viewpoint(p, owner) != ScenarioViewpoint::MixedLegacy {
|
||||
form = form.push(button("Create new source…").on_press(event(Event::Source(
|
||||
super::super::source_draft::Event::Open(d.invocation),
|
||||
))));
|
||||
} else {
|
||||
form=form.push(label("New source creation requires a strict viewpoint. Existing sources remain available."));
|
||||
}
|
||||
}
|
||||
if d.tool == Tool::Message {
|
||||
form = form.push(
|
||||
pick_list(
|
||||
vec![
|
||||
MessageStyle::Asynchronous,
|
||||
MessageStyle::Call,
|
||||
MessageStyle::CallReply,
|
||||
MessageStyle::Reply,
|
||||
MessageStyle::Create,
|
||||
MessageStyle::Delete,
|
||||
MessageStyle::Timer,
|
||||
],
|
||||
Some(d.style),
|
||||
|style| event(Event::Style(style)),
|
||||
)
|
||||
.width(Fill)
|
||||
.padding(9)
|
||||
.text_size(12),
|
||||
);
|
||||
if d.style == MessageStyle::Reply {
|
||||
form = form.push(bounded_picker(
|
||||
app.behavior.scenario.call_choices(p, context, d),
|
||||
d,
|
||||
d.call,
|
||||
"Choose the earlier call…",
|
||||
Event::Call,
|
||||
));
|
||||
if d.call.is_some() {
|
||||
form = form.push(label(
|
||||
"Reply reuses the call exchange in reverse and retains its correlation.",
|
||||
));
|
||||
}
|
||||
} else if d.style != MessageStyle::Timer {
|
||||
form = form.push(bounded_picker(
|
||||
exchanges(p, d),
|
||||
d,
|
||||
d.exchange,
|
||||
"Choose the exchange…",
|
||||
Event::Exchange,
|
||||
));
|
||||
form = form.push(label(
|
||||
"Apply checks that the message is valid at this insertion position.",
|
||||
));
|
||||
}
|
||||
form = form.push(picker(
|
||||
d.line_choices(p, true),
|
||||
d.sender,
|
||||
"Sending lifeline…",
|
||||
Event::Sender,
|
||||
));
|
||||
if d.style != MessageStyle::Timer {
|
||||
form = form.push(picker(
|
||||
d.line_choices(p, false),
|
||||
d.receiver,
|
||||
"Receiving lifeline…",
|
||||
Event::Receiver,
|
||||
));
|
||||
}
|
||||
if d.style == MessageStyle::Timer {
|
||||
form = form.push(
|
||||
text_input("Duration / deadline, e.g. 30 s", &d.expression)
|
||||
.on_input(|s| event(Event::Expression(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
if p.layer_of(owner) == Some(Layer::Sa)
|
||||
&& viewpoint(p, owner) == ScenarioViewpoint::BoundaryInterface
|
||||
&& matches!(
|
||||
d.style,
|
||||
MessageStyle::Call | MessageStyle::CallReply | MessageStyle::Asynchronous
|
||||
)
|
||||
{
|
||||
form = form.push(
|
||||
iced::widget::checkbox(d.operation.is_some())
|
||||
.label("Invoke a specific interface operation")
|
||||
.on_toggle(|enabled| event(Event::OperationIntent(enabled))),
|
||||
);
|
||||
if let Some(operation) = &d.operation {
|
||||
form = form
|
||||
.push(bounded_picker(
|
||||
crate::data_values::operation_choices(p, &d.proposed_message(p)),
|
||||
d,
|
||||
operation.allocation,
|
||||
"Choose the exact interface operation allocation…",
|
||||
Event::Operation,
|
||||
))
|
||||
.push(
|
||||
button("Keep operation unresolved")
|
||||
.on_press(event(Event::ClearOperation)),
|
||||
);
|
||||
if let Some(id) = operation.allocation {
|
||||
form = form.push(label(crate::data_values::operation_identity(p, id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(description) =
|
||||
crate::data_values::operation_label(p, &d.proposed_message(p))
|
||||
{
|
||||
form = form.push(label(description));
|
||||
}
|
||||
match d.signature(p) {
|
||||
Ok(Some(exchange)) => form = form.push(value_panel(p, d, &exchange)),
|
||||
Err(problem) => {
|
||||
form = form.push(label(problem));
|
||||
for (key, expression) in d.authored_values() {
|
||||
form = form
|
||||
.push(
|
||||
text(format!(
|
||||
"Retained value · {} / {}",
|
||||
key.path
|
||||
.iter()
|
||||
.map(|id| p.named(*id))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" → "),
|
||||
p.named(key.field)
|
||||
))
|
||||
.size(11),
|
||||
)
|
||||
.push(
|
||||
text_input("Value expression", expression)
|
||||
.on_input({
|
||||
let key = key.clone();
|
||||
move |raw| event(Event::Value(key.clone(), raw))
|
||||
})
|
||||
.padding(8)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
}
|
||||
if d.style == MessageStyle::CallReply {
|
||||
form=form.push(label("Creates the call and reversed, correlated reply together in one undoable operation."));
|
||||
}
|
||||
}
|
||||
if matches!(d.tool, Tool::Action | Tool::Observation) {
|
||||
form = form.push(picker(
|
||||
lines(p, owner),
|
||||
d.sender,
|
||||
"Observed lifeline…",
|
||||
Event::Sender,
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Reuse
|
||||
&& let Some(target) = d.target
|
||||
{
|
||||
for line in lines(p, target) {
|
||||
let referenced = line.id;
|
||||
let compatible: Vec<_> = lines(p, owner)
|
||||
.into_iter()
|
||||
.filter(|c| {
|
||||
compatible_binding(p, referenced, c.id)
|
||||
&& !d
|
||||
.bindings
|
||||
.iter()
|
||||
.any(|(r, l)| *r != referenced && *l == c.id)
|
||||
})
|
||||
.collect();
|
||||
if compatible.is_empty() {
|
||||
form = form.push(label(format!(
|
||||
"Add a compatible local lifeline before binding '{}'.",
|
||||
p.named(referenced)
|
||||
)));
|
||||
}
|
||||
form = form
|
||||
.push(label(format!("Bind {}", p.named(referenced))))
|
||||
.push(picker(
|
||||
compatible,
|
||||
d.bindings.get(&referenced).copied(),
|
||||
"Compatible local lifeline…",
|
||||
move |c| Event::Binding(referenced, c),
|
||||
} else if d.style != MessageStyle::Timer {
|
||||
form = form.push(bounded_picker(
|
||||
exchanges(p, d),
|
||||
d,
|
||||
d.exchange,
|
||||
"Choose the exchange…",
|
||||
Event::Exchange,
|
||||
));
|
||||
form = form.push(label(
|
||||
"Apply checks that the message is valid at this insertion position.",
|
||||
));
|
||||
}
|
||||
form = form.push(picker(
|
||||
d.line_choices(p, true),
|
||||
d.sender,
|
||||
"Sending lifeline…",
|
||||
Event::Sender,
|
||||
));
|
||||
if d.style != MessageStyle::Timer {
|
||||
form = form.push(picker(
|
||||
d.line_choices(p, false),
|
||||
d.receiver,
|
||||
"Receiving lifeline…",
|
||||
Event::Receiver,
|
||||
));
|
||||
}
|
||||
if d.style == MessageStyle::Timer {
|
||||
form = form.push(
|
||||
text_input("Duration / deadline, e.g. 30 s", &d.expression)
|
||||
.on_input(|s| event(Event::Expression(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
if p.layer_of(owner) == Some(Layer::Sa)
|
||||
&& viewpoint(p, owner) == ScenarioViewpoint::BoundaryInterface
|
||||
&& matches!(
|
||||
d.style,
|
||||
MessageStyle::Call | MessageStyle::CallReply | MessageStyle::Asynchronous
|
||||
)
|
||||
{
|
||||
form = form.push(
|
||||
iced::widget::checkbox(d.operation.is_some())
|
||||
.label("Invoke a specific interface operation")
|
||||
.on_toggle(|enabled| event(Event::OperationIntent(enabled))),
|
||||
);
|
||||
if let Some(operation) = &d.operation {
|
||||
form = form
|
||||
.push(bounded_picker(
|
||||
crate::data_values::operation_choices(p, &d.proposed_message(p)),
|
||||
d,
|
||||
operation.allocation,
|
||||
"Choose the exact interface operation allocation…",
|
||||
Event::Operation,
|
||||
))
|
||||
.push(
|
||||
button("Keep operation unresolved")
|
||||
.on_press(event(Event::ClearOperation)),
|
||||
);
|
||||
if let Some(id) = operation.allocation {
|
||||
form = form.push(label(crate::data_values::operation_identity(p, id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(description) =
|
||||
crate::data_values::operation_label(p, &d.proposed_message(p))
|
||||
{
|
||||
form = form.push(label(description));
|
||||
}
|
||||
match d.signature(p) {
|
||||
Ok(Some(exchange)) => form = form.push(value_panel(p, d, &exchange)),
|
||||
Err(problem) => {
|
||||
form = form.push(label(problem));
|
||||
for (key, expression) in d.authored_values() {
|
||||
form = form
|
||||
.push(
|
||||
text(format!(
|
||||
"Retained value · {} / {}",
|
||||
key.path
|
||||
.iter()
|
||||
.map(|id| p.named(*id))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" → "),
|
||||
p.named(key.field)
|
||||
))
|
||||
.size(11),
|
||||
)
|
||||
.push(
|
||||
text_input("Value expression", expression)
|
||||
.on_input({
|
||||
let key = key.clone();
|
||||
move |raw| event(Event::Value(key.clone(), raw))
|
||||
})
|
||||
.padding(8)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
}
|
||||
if d.style == MessageStyle::CallReply {
|
||||
form=form.push(label("Creates the call and reversed, correlated reply together in one undoable operation."));
|
||||
}
|
||||
}
|
||||
form = form.push(label(
|
||||
"Bindings are explicit, one-to-one and refer to existing lifelines.",
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Fragment {
|
||||
form = form.push(
|
||||
pick_list(
|
||||
vec![
|
||||
Operator(FragmentOperator::Alternative),
|
||||
Operator(FragmentOperator::Parallel),
|
||||
Operator(FragmentOperator::Loop),
|
||||
Operator(FragmentOperator::Optional),
|
||||
],
|
||||
Some(Operator(d.operator)),
|
||||
|o| event(Event::Operator(o)),
|
||||
)
|
||||
.padding(9)
|
||||
.text_size(12)
|
||||
.width(Fill),
|
||||
);
|
||||
if d.operator != FragmentOperator::Parallel {
|
||||
if matches!(d.tool, Tool::Action | Tool::Observation) {
|
||||
form = form.push(picker(
|
||||
lines(p, owner),
|
||||
d.sender,
|
||||
"Observed lifeline…",
|
||||
Event::Sender,
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Reuse
|
||||
&& let Some(target) = d.target
|
||||
{
|
||||
for line in lines(p, target) {
|
||||
let referenced = line.id;
|
||||
let compatible: Vec<_> = lines(p, owner)
|
||||
.into_iter()
|
||||
.filter(|c| {
|
||||
compatible_binding(p, referenced, c.id)
|
||||
&& !d
|
||||
.bindings
|
||||
.iter()
|
||||
.any(|(r, l)| *r != referenced && *l == c.id)
|
||||
})
|
||||
.collect();
|
||||
if compatible.is_empty() {
|
||||
form = form.push(label(format!(
|
||||
"Add a compatible local lifeline before binding '{}'.",
|
||||
p.named(referenced)
|
||||
)));
|
||||
}
|
||||
form = form
|
||||
.push(label(format!("Bind {}", p.named(referenced))))
|
||||
.push(picker(
|
||||
compatible,
|
||||
d.bindings.get(&referenced).copied(),
|
||||
"Compatible local lifeline…",
|
||||
move |c| Event::Binding(referenced, c),
|
||||
));
|
||||
}
|
||||
form = form.push(label(
|
||||
"Bindings are explicit, one-to-one and refer to existing lifelines.",
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Fragment {
|
||||
form = form.push(
|
||||
text_input("Condition / loop guard", &d.expression)
|
||||
.on_input(|s| event(Event::Expression(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
pick_list(
|
||||
vec![
|
||||
Operator(FragmentOperator::Alternative),
|
||||
Operator(FragmentOperator::Parallel),
|
||||
Operator(FragmentOperator::Loop),
|
||||
Operator(FragmentOperator::Optional),
|
||||
],
|
||||
Some(Operator(d.operator)),
|
||||
|o| event(Event::Operator(o)),
|
||||
)
|
||||
.padding(9)
|
||||
.text_size(12)
|
||||
.width(Fill),
|
||||
);
|
||||
if d.operator != FragmentOperator::Parallel {
|
||||
form = form.push(
|
||||
text_input("Condition / loop guard", &d.expression)
|
||||
.on_input(|s| event(Event::Expression(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
if d.operator == FragmentOperator::Alternative {
|
||||
form = form.push(
|
||||
text_input("Second alternative guard", &d.second_guard)
|
||||
.on_input(|s| event(Event::SecondGuard(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
form=form.push(label("Creates the fragment with its operands. Choose an operand as destination when adding messages or actions."));
|
||||
}
|
||||
if d.operator == FragmentOperator::Alternative {
|
||||
form = form.push(
|
||||
text_input("Second alternative guard", &d.second_guard)
|
||||
.on_input(|s| event(Event::SecondGuard(s)))
|
||||
.padding(9)
|
||||
.size(12),
|
||||
);
|
||||
let readiness = d.command(p);
|
||||
if let Err(error) = &readiness {
|
||||
form = form.push(label(error.clone()));
|
||||
}
|
||||
form=form.push(label("Creates the fragment with its operands. Choose an operand as destination when adding messages or actions."));
|
||||
let footer = row![
|
||||
button("Create")
|
||||
.padding(9)
|
||||
.on_press_maybe(readiness.is_ok().then_some(event(Event::Submit))),
|
||||
action("Cancel", event(Event::Cancel))
|
||||
]
|
||||
.spacing(7);
|
||||
form_panel = editor_panel(footer.into(), form.into());
|
||||
}
|
||||
let readiness = d.command(p);
|
||||
if let Err(error) = &readiness {
|
||||
form = form.push(label(error.clone()));
|
||||
}
|
||||
let footer = row![
|
||||
button("Create")
|
||||
.padding(9)
|
||||
.on_press_maybe(readiness.is_ok().then_some(event(Event::Submit))),
|
||||
action("Cancel", event(Event::Cancel))
|
||||
]
|
||||
.spacing(7);
|
||||
form_panel = editor_panel(footer.into(), form.into());
|
||||
}
|
||||
workspace_layout(header.into(), details, canvas, form_panel, pending)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
//! A prerequisite belongs to its pending consumer, never the accepted catalog.
|
||||
use iced::{
|
||||
Element as UiElement, Fill,
|
||||
widget::{button, column, container, row, scrollable, text, text_input},
|
||||
};
|
||||
use oa_core::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub const NAME_INPUT: &str = "behavior-source-name";
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Scope {
|
||||
Lifeline {
|
||||
owner: Id,
|
||||
viewpoint: ScenarioViewpoint,
|
||||
},
|
||||
Work {
|
||||
owner: Id,
|
||||
},
|
||||
Machine {
|
||||
layer: Layer,
|
||||
},
|
||||
}
|
||||
impl Scope {
|
||||
fn owner(self) -> Option<Id> {
|
||||
match self {
|
||||
Self::Lifeline { owner, .. } | Self::Work { owner } => Some(owner),
|
||||
Self::Machine { .. } => None,
|
||||
}
|
||||
}
|
||||
fn layer(self, p: &Project) -> Result<Layer, String> {
|
||||
match self {
|
||||
Self::Machine { layer } => Ok(layer),
|
||||
_ => p
|
||||
.layer_of(self.owner().unwrap())
|
||||
.ok_or("The consumer owner no longer exists.".into()),
|
||||
}
|
||||
}
|
||||
fn kinds(self, layer: Layer) -> Vec<Kind> {
|
||||
match self {
|
||||
Self::Work { .. } => vec![if layer == Layer::Oa {
|
||||
Kind::Activity
|
||||
} else {
|
||||
Kind::Function
|
||||
}],
|
||||
Self::Lifeline {
|
||||
viewpoint: ScenarioViewpoint::OperationalActivity,
|
||||
..
|
||||
} => vec![Kind::Activity],
|
||||
Self::Lifeline {
|
||||
viewpoint: ScenarioViewpoint::Functional,
|
||||
..
|
||||
} => vec![Kind::Function],
|
||||
Self::Lifeline {
|
||||
viewpoint: ScenarioViewpoint::ParticipantInteraction,
|
||||
..
|
||||
} => vec![Kind::Entity, Kind::Actor, Kind::Role],
|
||||
Self::Lifeline {
|
||||
viewpoint: ScenarioViewpoint::BoundaryInterface,
|
||||
..
|
||||
} => vec![Kind::System, Kind::SystemActor],
|
||||
Self::Machine { .. } if layer == Layer::Oa => vec![Kind::Entity, Kind::Actor],
|
||||
Self::Machine { .. } => vec![Kind::System, Kind::SystemActor],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Open(Id),
|
||||
Edit(Id, Edit),
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Edit {
|
||||
Name(String),
|
||||
Kind(Kind),
|
||||
Parent(Option<Id>),
|
||||
Search(String),
|
||||
Page(usize),
|
||||
Back,
|
||||
Use,
|
||||
}
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Draft {
|
||||
token: Id,
|
||||
document: Id,
|
||||
scope: Scope,
|
||||
layer: Layer,
|
||||
owner: Option<Element>,
|
||||
id: Id,
|
||||
kind: Option<Kind>,
|
||||
name: String,
|
||||
parent: Option<Element>,
|
||||
search: String,
|
||||
page: usize,
|
||||
identities: Vec<Id>,
|
||||
}
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct State {
|
||||
editing: Option<Draft>,
|
||||
staged: Option<Draft>,
|
||||
#[serde(default)]
|
||||
engaged: bool,
|
||||
}
|
||||
impl State {
|
||||
pub fn check_scope(&self, expected: Scope, selected: Option<Id>) -> Result<(), String> {
|
||||
if self
|
||||
.editing
|
||||
.as_ref()
|
||||
.or_else(|| self.staged.as_ref().filter(|d| Some(d.id) == selected))
|
||||
.is_some_and(|d| d.scope != expected)
|
||||
{
|
||||
return Err("The recovered source request belongs to a different consumer context. Go Back or cancel this draft.".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn dismiss(&mut self, event: &Event) -> Result<bool, String> {
|
||||
if let Event::Edit(token, Edit::Back) = event {
|
||||
if self.editing.as_ref().is_none_or(|d| d.token != *token) {
|
||||
return Err("This Back action belongs to a previous source form.".into());
|
||||
}
|
||||
self.editing = None;
|
||||
self.engaged = true;
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn engaged(&self) -> bool {
|
||||
self.engaged || self.editing.is_some() || self.staged.is_some()
|
||||
}
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.editing.is_some()
|
||||
}
|
||||
pub fn back(&mut self) -> bool {
|
||||
self.editing.take().is_some()
|
||||
}
|
||||
pub fn label(&self, selected: Option<Id>) -> Option<String> {
|
||||
self.staged
|
||||
.as_ref()
|
||||
.filter(|d| Some(d.id) == selected)
|
||||
.map(|d| {
|
||||
format!(
|
||||
"New · {} · {}",
|
||||
d.kind.map_or("Choose kind".into(), |k| k.to_string()),
|
||||
d.name
|
||||
)
|
||||
})
|
||||
}
|
||||
pub fn update(
|
||||
&mut self,
|
||||
p: &Project,
|
||||
scope: Scope,
|
||||
invocation: Id,
|
||||
event: Event,
|
||||
) -> Result<Option<Id>, String> {
|
||||
if self.dismiss(&event)? {
|
||||
return Ok(None);
|
||||
}
|
||||
match event {
|
||||
Event::Open(token) => {
|
||||
if token != invocation || self.is_open() {
|
||||
return Err("This source request is stale. Use the current form.".into());
|
||||
}
|
||||
let layer = scope.layer(p)?;
|
||||
let kinds = scope.kinds(layer);
|
||||
if kinds.is_empty() {
|
||||
return Err("Create new sources requires a strict scenario viewpoint; use an existing source here.".into());
|
||||
}
|
||||
self.engaged = true;
|
||||
self.editing = Some(Draft {
|
||||
token: Id::new_v4(),
|
||||
document: p.id,
|
||||
scope,
|
||||
layer,
|
||||
owner: scope.owner().and_then(|id| p.elements.get(&id).cloned()),
|
||||
id: Id::new_v4(),
|
||||
kind: (kinds.len() == 1).then_some(kinds[0]),
|
||||
name: String::new(),
|
||||
parent: None,
|
||||
search: String::new(),
|
||||
page: 0,
|
||||
identities: (0..match scope {
|
||||
Scope::Work { owner } => p.children(owner).count() + 4,
|
||||
Scope::Lifeline { .. } => 1,
|
||||
Scope::Machine { .. } => 0,
|
||||
})
|
||||
.map(|_| Id::new_v4())
|
||||
.collect(),
|
||||
});
|
||||
Ok(None)
|
||||
}
|
||||
Event::Edit(token, edit) => {
|
||||
let d = self
|
||||
.editing
|
||||
.as_mut()
|
||||
.filter(|d| d.token == token && d.scope == scope && d.document == p.id)
|
||||
.ok_or("This source response is stale; return to the current form.")?;
|
||||
match edit {
|
||||
Edit::Back => {
|
||||
self.editing = None;
|
||||
Ok(None)
|
||||
}
|
||||
Edit::Use => {
|
||||
d.command(p)?;
|
||||
let id = d.id;
|
||||
self.staged = self.editing.take();
|
||||
Ok(Some(id))
|
||||
}
|
||||
Edit::Name(name) => {
|
||||
d.name = name;
|
||||
Ok(None)
|
||||
}
|
||||
Edit::Kind(kind) => {
|
||||
if !scope.kinds(d.layer).contains(&kind) {
|
||||
return Err("Choose an explicitly supported source kind.".into());
|
||||
}
|
||||
d.kind = Some(kind);
|
||||
d.parent = None;
|
||||
d.page = 0;
|
||||
Ok(None)
|
||||
}
|
||||
Edit::Parent(parent) => {
|
||||
let kind = d.kind.ok_or("Choose the source kind first.")?;
|
||||
if !validation::can_parent(p, kind, d.layer, parent) {
|
||||
return Err("Choose a valid semantic parent.".into());
|
||||
}
|
||||
d.parent = parent.map(|id| p.elements[&id].clone());
|
||||
Ok(None)
|
||||
}
|
||||
Edit::Search(query) => {
|
||||
d.search = query;
|
||||
d.page = 0;
|
||||
Ok(None)
|
||||
}
|
||||
Edit::Page(page) => {
|
||||
d.page = page;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn preview(&self, p: &Project, selected: Option<Id>) -> Result<Option<Project>, String> {
|
||||
if self.is_open() {
|
||||
return Err("Use this new source or go Back before creating the consumer.".into());
|
||||
}
|
||||
self.staged
|
||||
.as_ref()
|
||||
.filter(|d| Some(d.id) == selected)
|
||||
.map(|d| execute_batch(p, &[d.command(p)?]).map_err(|e| e.to_string()))
|
||||
.transpose()
|
||||
}
|
||||
pub fn combine(
|
||||
&self,
|
||||
p: &Project,
|
||||
selected: Option<Id>,
|
||||
command: Command,
|
||||
) -> Result<Command, String> {
|
||||
let Some(d) = self.staged.as_ref().filter(|d| Some(d.id) == selected) else {
|
||||
return Ok(command);
|
||||
};
|
||||
let preview = execute_batch(p, &[d.command(p)?]).map_err(|e| e.to_string())?;
|
||||
let mut commands = match command {
|
||||
Command::Batch(commands) => commands,
|
||||
other => vec![other],
|
||||
};
|
||||
let fresh: Vec<_> = commands
|
||||
.iter()
|
||||
.filter(|_| !matches!(d.scope, Scope::Machine { .. }))
|
||||
.filter_map(|c| match c {
|
||||
Command::CreateElement(e) => Some(e.id),
|
||||
Command::CreateRelation(r) => Some(r.id),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
if fresh.len() > d.identities.len() {
|
||||
return Err(
|
||||
"The path grew beyond this draft. Return and create the source again.".into(),
|
||||
);
|
||||
}
|
||||
let replacements: BTreeMap<_, _> = fresh
|
||||
.into_iter()
|
||||
.zip(d.identities.iter().copied())
|
||||
.collect();
|
||||
if replacements.values().any(|id| preview.contains(*id)) {
|
||||
return Err(
|
||||
"A reserved consumer identity is already used. Start a fresh source draft.".into(),
|
||||
);
|
||||
}
|
||||
let remap = |id: &mut Id| {
|
||||
if let Some(new) = replacements.get(id) {
|
||||
*id = *new;
|
||||
}
|
||||
};
|
||||
for c in &mut commands {
|
||||
match c {
|
||||
Command::CreateElement(e) => {
|
||||
remap(&mut e.id);
|
||||
references::visit_element_refs(e, remap);
|
||||
e.alias = preview.fresh_alias(&e.name, "contribution", e.id);
|
||||
}
|
||||
Command::CreateRelation(r) => {
|
||||
remap(&mut r.id);
|
||||
references::visit_relation_refs(r, remap);
|
||||
r.alias = preview.fresh_alias(&r.name, "path", r.id);
|
||||
}
|
||||
Command::EditRelation(_, r) => references::visit_relation_refs(r, remap),
|
||||
Command::SetSteps(_, steps) => steps.iter_mut().for_each(remap),
|
||||
// Machine commands already carry their reserved identities.
|
||||
Command::CreateDiagram(_) | Command::Layout(_) => {}
|
||||
_ => return Err("Unsupported prerequisite consumer operation.".into()),
|
||||
}
|
||||
}
|
||||
commands.insert(0, d.command(p)?);
|
||||
let command = super::topology::unique_batch(p, commands);
|
||||
execute_batch(p, std::slice::from_ref(&command)).map_err(|e| e.to_string())?;
|
||||
Ok(command)
|
||||
}
|
||||
pub fn view<'a, R: iced::advanced::text::Renderer + 'a>(
|
||||
&'a self,
|
||||
p: &'a Project,
|
||||
) -> Option<UiElement<'a, Event, iced::Theme, R>> {
|
||||
let d = self.editing.as_ref()?;
|
||||
let event = move |edit| Event::Edit(d.token, edit);
|
||||
let mut fields = column![
|
||||
text(format!("New source · {}", d.layer)).size(18),
|
||||
text(match d.scope {
|
||||
Scope::Lifeline { owner, viewpoint } =>
|
||||
format!("For a lifeline in {} · {:?}", p.named(owner), viewpoint),
|
||||
Scope::Work { owner } => format!("For a contribution in {}", p.named(owner)),
|
||||
Scope::Machine { .. } => "Owner for the pending state machine".into(),
|
||||
})
|
||||
.size(12),
|
||||
text("The parent form is retained. This source is created only with its consumer.")
|
||||
.size(12)
|
||||
]
|
||||
.spacing(8);
|
||||
for kind in d.scope.kinds(d.layer) {
|
||||
fields = fields.push(
|
||||
button(text(kind.to_string()))
|
||||
.on_press(event(Edit::Kind(kind)))
|
||||
.style(if d.kind == Some(kind) {
|
||||
button::primary
|
||||
} else {
|
||||
button::secondary
|
||||
}),
|
||||
);
|
||||
}
|
||||
fields = fields.push(
|
||||
text_input("Source name (independent of the consumer name)", &d.name)
|
||||
.id(NAME_INPUT)
|
||||
.on_input(move |v| event(Edit::Name(v)))
|
||||
.padding(8),
|
||||
);
|
||||
fields = fields.push(
|
||||
text(format!(
|
||||
"Semantic parent: {}",
|
||||
d.parent
|
||||
.as_ref()
|
||||
.map_or(format!("{} layer root", d.layer), |e| format!(
|
||||
"{} · {} · @{}",
|
||||
e.name,
|
||||
e.kind(),
|
||||
e.alias
|
||||
))
|
||||
))
|
||||
.size(12),
|
||||
);
|
||||
if let Some(kind) = d.kind {
|
||||
fields = fields.push(button("Use layer root").on_press_maybe(
|
||||
validation::can_parent(p, kind, d.layer, None).then(|| event(Edit::Parent(None))),
|
||||
));
|
||||
fields = fields.push(
|
||||
text_input("Find a semantic parent (optional)", &d.search)
|
||||
.on_input(move |v| event(Edit::Search(v)))
|
||||
.padding(6),
|
||||
);
|
||||
let query = d.search.to_lowercase();
|
||||
let mut parents: Vec<_> = p
|
||||
.elements
|
||||
.values()
|
||||
.filter(|e| validation::can_parent(p, kind, d.layer, Some(e.id)))
|
||||
.map(|e| (e.id, super::creation::reference_label(p, e.id)))
|
||||
.filter(|(_, label)| label.to_lowercase().contains(&query))
|
||||
.collect();
|
||||
parents.sort_by(|a, b| a.1.cmp(&b.1).then(a.0.cmp(&b.0)));
|
||||
let page = d.page.min(parents.len().saturating_sub(1) / 6);
|
||||
for (id, label) in parents.iter().skip(page * 6).take(6) {
|
||||
fields = fields.push(
|
||||
button(text(label.clone()).size(12))
|
||||
.on_press(event(Edit::Parent(Some(*id))))
|
||||
.width(Fill),
|
||||
);
|
||||
}
|
||||
if parents.len() > 6 {
|
||||
fields = fields.push(
|
||||
row![
|
||||
button("Previous").on_press_maybe(
|
||||
(page > 0).then(|| event(Edit::Page(page.saturating_sub(1))))
|
||||
),
|
||||
text(format!("{} / {}", page + 1, parents.len().div_ceil(6))),
|
||||
button("Next").on_press_maybe(
|
||||
((page + 1) * 6 < parents.len()).then(|| event(Edit::Page(page + 1)))
|
||||
)
|
||||
]
|
||||
.spacing(6),
|
||||
);
|
||||
}
|
||||
}
|
||||
let ready = d.command(p);
|
||||
if let Err(error) = &ready {
|
||||
fields = fields.push(text(error.clone()).size(12));
|
||||
}
|
||||
Some(
|
||||
container(
|
||||
column![
|
||||
scrollable(fields).id("behavior-source-fields").height(Fill),
|
||||
container(
|
||||
row![
|
||||
button("Back · Esc").on_press(event(Edit::Back)),
|
||||
button("Use this new source")
|
||||
.on_press_maybe(ready.is_ok().then(|| event(Edit::Use)))
|
||||
]
|
||||
.spacing(8)
|
||||
)
|
||||
.id("behavior-source-actions")
|
||||
]
|
||||
.spacing(10),
|
||||
)
|
||||
.padding(12)
|
||||
.height(Fill)
|
||||
.width(Fill)
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Draft {
|
||||
fn command(&self, p: &Project) -> Result<Command, String> {
|
||||
if self.document != p.id
|
||||
|| self.scope.layer(p)? != self.layer
|
||||
|| self
|
||||
.owner
|
||||
.as_ref()
|
||||
.is_some_and(|e| p.elements.get(&e.id) != Some(e))
|
||||
{
|
||||
return Err(
|
||||
"The source request's document or consumer changed. Go Back and reopen Create new."
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
let kind = self
|
||||
.kind
|
||||
.filter(|kind| self.scope.kinds(self.layer).contains(kind))
|
||||
.ok_or("Choose the source kind explicitly.")?;
|
||||
if self.name.trim().is_empty() {
|
||||
return Err("Enter the source name.".into());
|
||||
}
|
||||
if p.contains(self.id) {
|
||||
return Err(
|
||||
"The reserved source identity is already used. Go Back and start again.".into(),
|
||||
);
|
||||
}
|
||||
let parent = self.parent.as_ref().map(|e| e.id);
|
||||
if self
|
||||
.parent
|
||||
.as_ref()
|
||||
.is_some_and(|e| p.elements.get(&e.id) != Some(e))
|
||||
|| !validation::can_parent(p, kind, self.layer, parent)
|
||||
{
|
||||
return Err("The semantic parent changed. Choose its intended parent again.".into());
|
||||
}
|
||||
let e = Element {
|
||||
id: self.id,
|
||||
alias: p.fresh_alias(&self.name, "source", self.id),
|
||||
name: self.name.clone(),
|
||||
description: String::new(),
|
||||
parent,
|
||||
body: ElementBody::new(kind, self.layer)
|
||||
.ok_or("This source kind is unavailable in this layer.")?,
|
||||
};
|
||||
let command = Command::CreateElement(e);
|
||||
execute_batch(p, std::slice::from_ref(&command)).map_err(|e| e.to_string())?;
|
||||
Ok(command)
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ impl Tool {
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
Source(super::source_draft::Event),
|
||||
Start(Id, Tool, Option<Id>),
|
||||
Cancel,
|
||||
Submit,
|
||||
@@ -90,15 +91,22 @@ pub struct State {
|
||||
selected_context: Option<oa_core::topology_context::ContextAddress>,
|
||||
shelf: Option<Shelf>,
|
||||
}
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Browser {
|
||||
search: String,
|
||||
page: usize,
|
||||
}
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Draft {
|
||||
#[serde(default)]
|
||||
source: super::source_draft::State,
|
||||
#[serde(default = "Id::new_v4")]
|
||||
invocation: Id,
|
||||
#[serde(default)]
|
||||
source_origin: Option<(Id, oa_core::Element)>,
|
||||
|
||||
#[serde(with = "recovery_insertion")]
|
||||
insertion: Insertion,
|
||||
fixed: bool,
|
||||
@@ -117,6 +125,28 @@ struct Draft {
|
||||
contextual: Option<contextual::Draft>,
|
||||
}
|
||||
impl State {
|
||||
pub(super) fn pending_name(&self) -> Option<&str> {
|
||||
self.draft.as_ref().map(|d| d.name.as_str())
|
||||
}
|
||||
pub(super) fn source_view<'a>(&'a self, p: &'a Project) -> Option<iced::Element<'a, Event>> {
|
||||
self.draft
|
||||
.as_ref()?
|
||||
.source
|
||||
.view(p)
|
||||
.map(|v| v.map(Event::Source))
|
||||
}
|
||||
|
||||
pub fn source_active(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.engaged())
|
||||
}
|
||||
|
||||
pub fn source_open(&self) -> bool {
|
||||
self.draft.as_ref().is_some_and(|d| d.source.is_open())
|
||||
}
|
||||
pub fn source_back(&mut self) -> bool {
|
||||
self.draft.as_mut().is_some_and(|d| d.source.back())
|
||||
}
|
||||
|
||||
pub(super) fn recovery_snapshot(&self) -> Result<Option<serde_json::Value>, String> {
|
||||
self.draft
|
||||
.as_ref()
|
||||
@@ -152,6 +182,58 @@ impl State {
|
||||
}
|
||||
|
||||
pub fn update(&mut self, p: &Project, event: Event) -> Result<Option<Command>, String> {
|
||||
if let Event::Source(event) = event {
|
||||
if self
|
||||
.draft
|
||||
.as_mut()
|
||||
.ok_or("Start the consumer form first.")?
|
||||
.source
|
||||
.dismiss(&event)?
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
let d = self
|
||||
.draft
|
||||
.as_ref()
|
||||
.ok_or("Start the consumer form first.")?;
|
||||
if d.tool != Tool::Work {
|
||||
return Err("This reference does not support staged source creation.".into());
|
||||
}
|
||||
if d.source_origin.as_ref().is_some_and(|(document, owner)| {
|
||||
*document != p.id || p.elements.get(&d.owner) != Some(owner)
|
||||
}) {
|
||||
return Err("The original consumer changed. Cancel and reopen its form; the current draft is retained.".into());
|
||||
}
|
||||
if d.source_origin.is_none() && d.source.engaged() {
|
||||
return Err("The recovered source draft has no original document binding. Go Back or cancel it.".into());
|
||||
}
|
||||
let mut next = d.clone();
|
||||
if next.source_origin.is_none() && matches!(&event, super::source_draft::Event::Open(_))
|
||||
{
|
||||
next.source_origin = Some((
|
||||
p.id,
|
||||
p.elements
|
||||
.get(&d.owner)
|
||||
.ok_or("The consumer owner no longer exists.")?
|
||||
.clone(),
|
||||
));
|
||||
}
|
||||
if let Some(id) = next.source.update(
|
||||
p,
|
||||
super::source_draft::Scope::Work { owner: d.owner },
|
||||
d.invocation,
|
||||
event,
|
||||
)? {
|
||||
next.target = Some(id);
|
||||
next.command(p)?;
|
||||
}
|
||||
self.draft = Some(next);
|
||||
return Ok(None);
|
||||
}
|
||||
if self.source_open() && !matches!(&event, Event::Cancel) {
|
||||
return Err("Use the new source or go Back before editing the parent form.".into());
|
||||
}
|
||||
|
||||
if self.draft.is_some() && matches!(&event, Event::Start(..)) {
|
||||
return Err(PENDING_DRAFT.into());
|
||||
}
|
||||
@@ -184,6 +266,9 @@ impl State {
|
||||
}
|
||||
});
|
||||
self.draft = Some(Draft {
|
||||
source: Default::default(),
|
||||
invocation: Id::new_v4(),
|
||||
source_origin: Some((p.id, p.elements[&owner].clone())),
|
||||
insertion: Insertion::default(),
|
||||
fixed: false,
|
||||
browsers: Default::default(),
|
||||
@@ -508,6 +593,22 @@ fn link(p: &Project, source: Id, target: Id, guard: &str) -> Command {
|
||||
}
|
||||
impl Draft {
|
||||
fn command(&self, p: &Project) -> Result<Command, String> {
|
||||
if self.source.engaged()
|
||||
&& self.source_origin.as_ref().is_none_or(|(document, owner)| {
|
||||
*document != p.id || p.elements.get(&self.owner) != Some(owner)
|
||||
})
|
||||
{
|
||||
return Err("The original consumer document or owner changed. Cancel and reopen its form; your draft is retained.".into());
|
||||
}
|
||||
self.source.check_scope(
|
||||
super::source_draft::Scope::Work { owner: self.owner },
|
||||
self.target,
|
||||
)?;
|
||||
let preview = self.source.preview(p, self.target)?;
|
||||
let command = self.consumer_command(preview.as_ref().unwrap_or(p))?;
|
||||
self.source.combine(p, self.target, command)
|
||||
}
|
||||
fn consumer_command(&self, p: &Project) -> Result<Command, String> {
|
||||
let owner = p
|
||||
.elements
|
||||
.get(&self.owner)
|
||||
@@ -615,6 +716,8 @@ impl Draft {
|
||||
});
|
||||
let name = if self.name.trim().is_empty() {
|
||||
default_name
|
||||
} else if self.source.label(self.target).is_some() {
|
||||
self.name.as_str()
|
||||
} else {
|
||||
self.name.trim()
|
||||
};
|
||||
@@ -1587,6 +1690,9 @@ mod tests {
|
||||
}
|
||||
fn branch(owner: Id, a: Id, b: Id, before: Id, after: Id) -> Draft {
|
||||
Draft {
|
||||
source: Default::default(),
|
||||
invocation: Id::new_v4(),
|
||||
source_origin: None,
|
||||
insertion: Insertion::default(),
|
||||
fixed: false,
|
||||
browsers: Default::default(),
|
||||
|
||||
@@ -33,7 +33,7 @@ pub enum Event {
|
||||
Search(String),
|
||||
Page(usize),
|
||||
}
|
||||
#[derive(Default, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub(super) struct Draft {
|
||||
edit: Option<Id>,
|
||||
|
||||
@@ -206,8 +206,16 @@ impl State {
|
||||
}
|
||||
None
|
||||
}
|
||||
pub(crate) fn created_selection(&self, command: &Command) -> Option<Id> {
|
||||
pub(crate) fn created_selection(&self, p: &Project, command: &Command) -> Option<Id> {
|
||||
let owner = self.pending_owner()?;
|
||||
if self
|
||||
.draft
|
||||
.as_ref()
|
||||
.is_some_and(|d| d.source.label(d.target).is_some())
|
||||
&& self.prepare_pending(p).ok().as_ref() != Some(command)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
if let Command::CreateRelation(r) | Command::EditRelation(_, r) = command
|
||||
&& matches!(&r.body, RelationBody::ContextualLink { owner: caller, .. } if *caller == owner)
|
||||
{
|
||||
|
||||
@@ -369,6 +369,25 @@ pub(super) fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Ele
|
||||
.width(Fill)
|
||||
.height(Fill)
|
||||
.style(style::card);
|
||||
if !pending && !p.children(owner).any(|e| is_contribution(p, owner, e.id)) {
|
||||
let title = if p.layer_of(owner) == Some(Layer::Oa) {
|
||||
"Add first activity contribution"
|
||||
} else {
|
||||
"Add first function contribution"
|
||||
};
|
||||
header = header.push(button(title).on_press_maybe(
|
||||
(!app.behavior.has_pending() && !app.draft_dirty() && !app.source_dirty()).then(
|
||||
|| {
|
||||
Message::TopologyCanvas(CanvasEvent::Begin {
|
||||
context,
|
||||
tool: Tool::Work,
|
||||
control: ControlKind::Choice,
|
||||
insertion: Insertion::default(),
|
||||
})
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
let details: Element<'_, Message> = match state.shelf {
|
||||
Some(Shelf::Tools) => controls.into(),
|
||||
_ => navigation.push(text("Full qualified identities and definition actions appear here for the selected contribution or link.").size(11)).into(),
|
||||
@@ -383,201 +402,223 @@ pub(super) fn view<'a>(app: &'a App, owner: Id, out: Column<'a, Message>) -> Ele
|
||||
};
|
||||
let mut form_panel: Element<'_, Message> = iced::widget::Space::new().height(0).into();
|
||||
if let Some(d) = state.draft.as_ref().filter(|d| d.owner == owner) {
|
||||
let mut form = column![text(d.tool.title()).size(16)].spacing(8);
|
||||
if let Some(contextual) = &d.contextual {
|
||||
form = form
|
||||
.push(
|
||||
text_input("Link name (retain current when blank)", &d.name)
|
||||
.on_input(|v| event(Event::Name(v)))
|
||||
.padding(8)
|
||||
.size(12),
|
||||
)
|
||||
.push(super::contextual::view(p, owner, contextual));
|
||||
if let Some(child) = d.source.view(p) {
|
||||
form_panel = column![
|
||||
text(format!(
|
||||
"Consumer name: {}",
|
||||
crate::views::short(&d.name, 60)
|
||||
))
|
||||
.size(12),
|
||||
child.map(|e| event(Event::Source(e)))
|
||||
]
|
||||
.spacing(6)
|
||||
.height(Fill)
|
||||
.into();
|
||||
} else {
|
||||
if let Some(link) = d.insertion.link.and_then(|id| p.relations.get(&id)) {
|
||||
let guard = if let RelationBody::SequenceLink { guard, .. } = &link.body {
|
||||
guard.as_str()
|
||||
} else {
|
||||
""
|
||||
};
|
||||
form = form.push(label(format!(
|
||||
"Insert on {} → {} · preserve path identity and condition [{}]",
|
||||
p.named(link.source()),
|
||||
p.named(link.target()),
|
||||
guard
|
||||
)));
|
||||
} else if d.fixed && ordered {
|
||||
form = form.push(label(match (d.before, d.after) {
|
||||
(Some(before), Some(after)) => format!(
|
||||
"Insert between {} → {} · preserve the ordered path",
|
||||
p.named(before),
|
||||
p.named(after)
|
||||
),
|
||||
(Some(before), None) => format!("Continue after {}", p.named(before)),
|
||||
(None, Some(after)) => format!("Insert before {}", p.named(after)),
|
||||
_ => "Start the ordered path".into(),
|
||||
}));
|
||||
} else if d.fixed
|
||||
&& d.tool == Tool::Exchange
|
||||
&& let Some(before) = d.before
|
||||
{
|
||||
form = form.push(label(format!(
|
||||
"Append after {} → new exchange · Create adds an explicit sequence link",
|
||||
p.named(before)
|
||||
)));
|
||||
} else if d.fixed && d.tool != Tool::Connect {
|
||||
form = form.push(label(
|
||||
d.insertion
|
||||
.before
|
||||
.map_or("Append an unconnected contribution".into(), |id| {
|
||||
format!("Unconnected contribution before {}", p.named(id))
|
||||
}),
|
||||
));
|
||||
}
|
||||
if !legacy_order(p, owner).is_empty() {
|
||||
form = form.push(label(
|
||||
let mut form = column![text(d.tool.title()).size(16)].spacing(8);
|
||||
if let Some(contextual) = &d.contextual {
|
||||
form = form
|
||||
.push(
|
||||
text_input("Link name (retain current when blank)", &d.name)
|
||||
.on_input(|v| event(Event::Name(v)))
|
||||
.padding(8)
|
||||
.size(12),
|
||||
)
|
||||
.push(super::contextual::view(p, owner, contextual));
|
||||
} else {
|
||||
if let Some(link) = d.insertion.link.and_then(|id| p.relations.get(&id)) {
|
||||
let guard = if let RelationBody::SequenceLink { guard, .. } = &link.body {
|
||||
guard.as_str()
|
||||
} else {
|
||||
""
|
||||
};
|
||||
form = form.push(label(format!(
|
||||
"Insert on {} → {} · preserve path identity and condition [{}]",
|
||||
p.named(link.source()),
|
||||
p.named(link.target()),
|
||||
guard
|
||||
)));
|
||||
} else if d.fixed && ordered {
|
||||
form = form.push(label(match (d.before, d.after) {
|
||||
(Some(before), Some(after)) => format!(
|
||||
"Insert between {} → {} · preserve the ordered path",
|
||||
p.named(before),
|
||||
p.named(after)
|
||||
),
|
||||
(Some(before), None) => format!("Continue after {}", p.named(before)),
|
||||
(None, Some(after)) => format!("Insert before {}", p.named(after)),
|
||||
_ => "Start the ordered path".into(),
|
||||
}));
|
||||
} else if d.fixed
|
||||
&& d.tool == Tool::Exchange
|
||||
&& let Some(before) = d.before
|
||||
{
|
||||
form = form.push(label(format!(
|
||||
"Append after {} → new exchange · Create adds an explicit sequence link",
|
||||
p.named(before)
|
||||
)));
|
||||
} else if d.fixed && d.tool != Tool::Connect {
|
||||
form = form.push(label(
|
||||
d.insertion
|
||||
.before
|
||||
.map_or("Append an unconnected contribution".into(), |id| {
|
||||
format!("Unconnected contribution before {}", p.named(id))
|
||||
}),
|
||||
));
|
||||
}
|
||||
if d.tool == Tool::Work {
|
||||
if let Some(title) = d.source.label(d.target) {
|
||||
form = form.push(label(title)).push(label("Create commits the new work and contribution together at the chosen path position."));
|
||||
}
|
||||
form = form.push(button("Create new source…").on_press(event(Event::Source(
|
||||
super::super::source_draft::Event::Open(d.invocation),
|
||||
))));
|
||||
}
|
||||
if !legacy_order(p, owner).is_empty() {
|
||||
form = form.push(label(
|
||||
"This edit preserves the ordered path as explicit links in the same undo step.",
|
||||
));
|
||||
}
|
||||
if matches!(
|
||||
d.tool,
|
||||
Tool::Work | Tool::Exchange | Tool::Reuse | Tool::Branch
|
||||
) {
|
||||
let choices = targets(p, owner, d.tool)
|
||||
.into_iter()
|
||||
.filter(|c| compatible_source(p, d, c.id))
|
||||
.collect();
|
||||
if d.tool == Tool::Branch {
|
||||
form = form.push(label("First path work"));
|
||||
}
|
||||
form = form.push(picker(
|
||||
choices,
|
||||
d,
|
||||
0,
|
||||
d.target,
|
||||
if matches!(
|
||||
d.tool,
|
||||
Tool::Work | Tool::Exchange | Tool::Reuse | Tool::Branch
|
||||
) {
|
||||
let choices = targets(p, owner, d.tool)
|
||||
.into_iter()
|
||||
.filter(|c| compatible_source(p, d, c.id))
|
||||
.collect();
|
||||
if d.tool == Tool::Branch {
|
||||
"Choose first path work…"
|
||||
form = form.push(label("First path work"));
|
||||
}
|
||||
form = form.push(picker(
|
||||
choices,
|
||||
d,
|
||||
0,
|
||||
d.target,
|
||||
if d.tool == Tool::Branch {
|
||||
"Choose first path work…"
|
||||
} else {
|
||||
"Choose existing source…"
|
||||
},
|
||||
Event::Target,
|
||||
));
|
||||
}
|
||||
if d.tool != Tool::Connect {
|
||||
form = form.push(
|
||||
text_input("Contribution name (defaults to source)", &d.name)
|
||||
.on_input(|v| event(Event::Name(v)))
|
||||
.padding(8)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
if matches!(d.tool, Tool::Control | Tool::Branch) {
|
||||
let kinds = if d.tool == Tool::Branch {
|
||||
vec![ControlKind::Choice, ControlKind::Fork]
|
||||
} else {
|
||||
"Choose existing source…"
|
||||
},
|
||||
Event::Target,
|
||||
));
|
||||
}
|
||||
if d.tool != Tool::Connect {
|
||||
form = form.push(
|
||||
text_input("Contribution name (defaults to source)", &d.name)
|
||||
.on_input(|v| event(Event::Name(v)))
|
||||
vec![
|
||||
ControlKind::Choice,
|
||||
ControlKind::Merge,
|
||||
ControlKind::Fork,
|
||||
ControlKind::Join,
|
||||
ControlKind::Loop,
|
||||
]
|
||||
};
|
||||
form = form.push(
|
||||
pick_list(
|
||||
kinds.into_iter().map(ControlChoice).collect::<Vec<_>>(),
|
||||
Some(ControlChoice(d.control)),
|
||||
|v| event(Event::Control(v)),
|
||||
)
|
||||
.padding(8)
|
||||
.text_size(12),
|
||||
);
|
||||
}
|
||||
if d.tool == Tool::Branch {
|
||||
form = form.push(label("Second path work")).push(picker(
|
||||
targets(p, owner, Tool::Work),
|
||||
d,
|
||||
1,
|
||||
d.alternate,
|
||||
"Second path work…",
|
||||
Event::Alternate,
|
||||
));
|
||||
if d.control != ControlKind::Fork {
|
||||
form = form
|
||||
.push(label("First path guard"))
|
||||
.push(
|
||||
text_input("First path guard", &d.guard)
|
||||
.on_input(|v| event(Event::Guard(v)))
|
||||
.padding(8),
|
||||
)
|
||||
.push(label("Second path guard"))
|
||||
.push(
|
||||
text_input("Second path guard (e.g. else)", &d.alternate_guard)
|
||||
.on_input(|v| event(Event::AlternateGuard(v)))
|
||||
.padding(8),
|
||||
);
|
||||
}
|
||||
}
|
||||
if d.fixed {
|
||||
if let (Some(a), Some(b)) = (d.before, d.after) {
|
||||
form = form.push(label(format!("{} → {}", p.named(a), p.named(b))));
|
||||
}
|
||||
} else {
|
||||
form = form
|
||||
.push(label("Preceding contribution"))
|
||||
.push(picker(
|
||||
contributions(p, owner),
|
||||
d,
|
||||
2,
|
||||
d.before,
|
||||
"After contribution…",
|
||||
Event::Before,
|
||||
))
|
||||
.push(button("Clear preceding").on_press(event(Event::ClearBefore)))
|
||||
.push(label("Following contribution"))
|
||||
.push(picker(
|
||||
contributions(p, owner),
|
||||
d,
|
||||
3,
|
||||
d.after,
|
||||
"Before contribution…",
|
||||
Event::After,
|
||||
))
|
||||
.push(button("Clear following").on_press(event(Event::ClearAfter)));
|
||||
}
|
||||
if d.tool != Tool::Branch
|
||||
&& d.insertion.link.is_none()
|
||||
&& (d.before.is_some() || d.tool == Tool::Connect)
|
||||
{
|
||||
form = form.push(
|
||||
text_input(
|
||||
"Path condition (empty remains a Choice / Loop warning)",
|
||||
&d.guard,
|
||||
)
|
||||
.on_input(|v| event(Event::Guard(v)))
|
||||
.padding(8)
|
||||
.size(12),
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
if matches!(d.tool, Tool::Control | Tool::Branch) {
|
||||
let kinds = if d.tool == Tool::Branch {
|
||||
vec![ControlKind::Choice, ControlKind::Fork]
|
||||
let valid = match d.command(p) {
|
||||
Ok(_) => true,
|
||||
Err(problem) => {
|
||||
form = form.push(label(problem));
|
||||
false
|
||||
}
|
||||
};
|
||||
let actions = row![
|
||||
button(if d.contextual.is_some() {
|
||||
"Apply link"
|
||||
} else {
|
||||
vec![
|
||||
ControlKind::Choice,
|
||||
ControlKind::Merge,
|
||||
ControlKind::Fork,
|
||||
ControlKind::Join,
|
||||
ControlKind::Loop,
|
||||
]
|
||||
};
|
||||
form = form.push(
|
||||
pick_list(
|
||||
kinds.into_iter().map(ControlChoice).collect::<Vec<_>>(),
|
||||
Some(ControlChoice(d.control)),
|
||||
|v| event(Event::Control(v)),
|
||||
)
|
||||
.padding(8)
|
||||
.text_size(12),
|
||||
);
|
||||
}
|
||||
if d.tool == Tool::Branch {
|
||||
form = form.push(label("Second path work")).push(picker(
|
||||
targets(p, owner, Tool::Work),
|
||||
d,
|
||||
1,
|
||||
d.alternate,
|
||||
"Second path work…",
|
||||
Event::Alternate,
|
||||
));
|
||||
if d.control != ControlKind::Fork {
|
||||
form = form
|
||||
.push(label("First path guard"))
|
||||
.push(
|
||||
text_input("First path guard", &d.guard)
|
||||
.on_input(|v| event(Event::Guard(v)))
|
||||
.padding(8),
|
||||
)
|
||||
.push(label("Second path guard"))
|
||||
.push(
|
||||
text_input("Second path guard (e.g. else)", &d.alternate_guard)
|
||||
.on_input(|v| event(Event::AlternateGuard(v)))
|
||||
.padding(8),
|
||||
);
|
||||
}
|
||||
}
|
||||
if d.fixed {
|
||||
if let (Some(a), Some(b)) = (d.before, d.after) {
|
||||
form = form.push(label(format!("{} → {}", p.named(a), p.named(b))));
|
||||
}
|
||||
} else {
|
||||
form = form
|
||||
.push(label("Preceding contribution"))
|
||||
.push(picker(
|
||||
contributions(p, owner),
|
||||
d,
|
||||
2,
|
||||
d.before,
|
||||
"After contribution…",
|
||||
Event::Before,
|
||||
))
|
||||
.push(button("Clear preceding").on_press(event(Event::ClearBefore)))
|
||||
.push(label("Following contribution"))
|
||||
.push(picker(
|
||||
contributions(p, owner),
|
||||
d,
|
||||
3,
|
||||
d.after,
|
||||
"Before contribution…",
|
||||
Event::After,
|
||||
))
|
||||
.push(button("Clear following").on_press(event(Event::ClearAfter)));
|
||||
}
|
||||
if d.tool != Tool::Branch
|
||||
&& d.insertion.link.is_none()
|
||||
&& (d.before.is_some() || d.tool == Tool::Connect)
|
||||
{
|
||||
form = form.push(
|
||||
text_input(
|
||||
"Path condition (empty remains a Choice / Loop warning)",
|
||||
&d.guard,
|
||||
)
|
||||
.on_input(|v| event(Event::Guard(v)))
|
||||
.padding(8)
|
||||
.size(12),
|
||||
);
|
||||
}
|
||||
"Create"
|
||||
})
|
||||
.on_press_maybe(valid.then(|| event(Event::Submit))),
|
||||
button("Cancel").on_press(event(Event::Cancel))
|
||||
]
|
||||
.spacing(7);
|
||||
form_panel = editor_panel(actions.into(), form.into());
|
||||
}
|
||||
let valid = match d.command(p) {
|
||||
Ok(_) => true,
|
||||
Err(problem) => {
|
||||
form = form.push(label(problem));
|
||||
false
|
||||
}
|
||||
};
|
||||
let actions = row![
|
||||
button(if d.contextual.is_some() {
|
||||
"Apply link"
|
||||
} else {
|
||||
"Create"
|
||||
})
|
||||
.on_press_maybe(valid.then(|| event(Event::Submit))),
|
||||
button("Cancel").on_press(event(Event::Cancel))
|
||||
]
|
||||
.spacing(7);
|
||||
form_panel = editor_panel(actions.into(), form.into());
|
||||
}
|
||||
panes(diagram, form_panel, pending)
|
||||
}
|
||||
|
||||
@@ -445,9 +445,9 @@ fn article(topic: Topic) -> Article {
|
||||
walkthrough(
|
||||
"Describe a path through exchanges",
|
||||
&[
|
||||
"First create the activities/functions and their exchanges. Check the source and target work for every exchange.",
|
||||
"A blank path offers Add first activity/function contribution. You can use existing work or stage a new source in that form; exchanges still need explicit compatible source and target work.",
|
||||
"Open Behavior & scenarios → New. Choose Operational process in OA or Functional chain in SA, enter its exact name, then Create and open. The new behavior belongs at the layer root and opens immediately; Undo removes the creation as one edit.",
|
||||
"Open Tools and choose Work or Exchange, then a highlighted path or contribution position to involve an existing source. Each contribution keeps its own identity while referring to the shared engineering definition.",
|
||||
"Open Tools and choose Work or Exchange, then a highlighted position. In Work, Create new source keeps the contribution name and position while you name its Activity/Function and choose its semantic parent. Use this new source stages it; Create commits source and contribution in one Undo. An adjacent exchange may require a particular existing work identity.",
|
||||
"In Tools, choose Sequence link and click or drag from the preceding contribution to the following contribution. Choose Tools → Select / reorder to drag a selected path endpoint and reconnect it; a contribution's ↕ handle changes its position within a column. These are local contributions and sequence links, not new architecture exchanges.",
|
||||
"Select a contribution, then add another after it. Tools → Two paths… creates a split, two paths and their merge in one undoable edit. Enter explicit alternative conditions. Fit overview uses the visible canvas area; 100% keeps working scale with scrollbars. If the minimum zoom is reached, scroll to inspect the remainder.",
|
||||
"Use Chain involvement from the Process/Functional chain to the capability it supports. Read Model checks for unfinished or disconnected paths.",
|
||||
@@ -490,7 +490,7 @@ fn article(topic: Topic) -> Article {
|
||||
"Create a scenario",
|
||||
&[
|
||||
"Open Behavior & scenarios → New → Scenario and enter its name. Explicitly choose Activities or Participants in OA, or Functions or System boundary in SA. Add optional context only when needed: this is a reference, while the scenario itself belongs at the layer root. Create and open starts the empty scenario.",
|
||||
"Use + Lifeline and choose the participant or work it represents. Choices follow the scenario's viewpoint: operational activities, operational participants, system functions or system boundary participants.",
|
||||
"Use Add first lifeline on an empty scenario, or + Lifeline. Choose existing work/participant or Create new source. The explicit viewpoint limits its kinds; choose participant kinds deliberately. Source name and lifeline name are separate, and the source semantic parent is independent of the scenario. No allocation or capability involvement is inferred.",
|
||||
"Choose + Message and its style. Call + correlated reply creates both occurrences in one edit. Select the exchange and compatible sending/receiving lifelines. Reply to existing call offers valid unanswered calls.",
|
||||
"Use Action, Observe state or Fragment for other behavior. A local timer has an expression and a lifeline, with no global exchange. Create and delete messages describe participant lifetime; Model checks also flag risks inside repeated loops.",
|
||||
"Choose a message style and Draw message. Start at a highlighted sequence position on a lifeline, then click or drag to the receiving lifeline. The form retains the chosen position while you select the exchange and details. Escape cancels the gesture.",
|
||||
@@ -543,7 +543,8 @@ fn article(topic: Topic) -> Article {
|
||||
walkthrough(
|
||||
"Build a state machine",
|
||||
&[
|
||||
"In Behavior & scenarios → New → State machine, enter its name and search for the existing same-layer participant that owns it. Candidate labels show parent context and alias to distinguish repeated names. If the participant does not exist yet, cancel and create it in Architecture first.",
|
||||
"In Behavior & scenarios → New → State machine, enter its name and search for the existing same-layer participant that owns it. Candidate labels show parent context and alias to distinguish repeated names.",
|
||||
"If the owner does not exist, Create new owner retains the machine name and first-view option. Choose its participant kind and semantic parent explicitly. Use this new source returns without changing the model; Create and open commits owner, machine and optional view together.",
|
||||
"Optionally select Create the first state view, then Create and open. The new machine starts without regions or states. For an existing machine, Create diagram places its existing regions and vertices in a saved view; + View creates another independent layout.",
|
||||
"Choose + Region and click the highlighted machine, or a State/Mode for a nested region. Choose Initial, State, Mode or another kind from + State / symbol, then click its highlighted owning region. Rename the new element in Properties.",
|
||||
"Choose Transition and drag from a source vertex to a compatible target, or click the source and then the target. In Select / move, drag states or containers to arrange them; a container moves its descendant placements without changing ownership.",
|
||||
@@ -897,7 +898,7 @@ fn article(topic: Topic) -> Article {
|
||||
),
|
||||
explain(
|
||||
"A new behavior is still a draft",
|
||||
"Behavior → New keeps the exact name, owner and viewpoint choices outside the model until Create and open succeeds. Cancel or Escape discards only this draft; if a dialog is open, the first Escape dismisses that dialog. New refuses other unfinished property, source or behavior drafts without applying them. Recovery restores the creation form in its original layer, including rejected raw text, for correction or cancellation.",
|
||||
"Inside a source subform, Back or the first Escape returns to the unchanged parent. Use this new source stages the prerequisite only. Canceling the parent discards it; choosing an existing reference excludes the staged source from creation. Recovery retains both forms and their reserved identities. An open dialog still receives Escape first. Behavior → New keeps the exact name, owner and viewpoint choices outside the model until Create and open succeeds. Cancel or Escape discards only this draft; if a dialog is open, the first Escape dismisses that dialog. New refuses other unfinished property, source or behavior drafts without applying them. Recovery restores the creation form in its original layer, including rejected raw text, for correction or cancellation.",
|
||||
),
|
||||
explain(
|
||||
"Aliases and references",
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# Contextual-source verification evidence, 2026-09-11
|
||||
|
||||
Codex-9e8r6t /root/release_audit. Root authorized this preservation-only directory while running separate native checks. No new tests, compilation, GUI actions, source edits, Git staging or publication were performed to create this archive.
|
||||
|
||||
## Scope and byte preservation
|
||||
|
||||
The 37 original records (201,835 bytes) were copied byte-for-byte from the two private evidence directories. `inventory.json` records their original repository-relative paths, sizes and SHA-256 values, plus the generated README and source readback record. It excludes itself to avoid a recursive hash. The directory contains 40 files total. No executable, DLL, rlib, model output, credential or dependency tree is included.
|
||||
|
||||
`desktop/` preserves the original relative layout of `.local/contextual-source-20260911/`. `oracle-preparation/` preserves concise records from `.local/staged-source-oracle-20260911/`. Embedded paths, timestamps, line endings, compiler diagnostics and manifest wording are deliberately unmodified. They describe the original host and run; they do not assert that private executables or dependency paths exist in another checkout.
|
||||
|
||||
Root should preserve these bytes through Git using the same narrow attribute convention as neighboring experiments:
|
||||
|
||||
```gitattributes
|
||||
harness/experiments/contextual-source-20260911/** -text whitespace=cr-at-eol
|
||||
```
|
||||
|
||||
This worker did not modify the root attributes or index. The existing global text normalization would otherwise change some CRLF records. Verify every inventory hash again after staging or a checkout with that rule.
|
||||
|
||||
## Results and distinct source snapshots
|
||||
|
||||
| Evidence | Meaning |
|
||||
| --- | --- |
|
||||
| `desktop/focused1*` | Missing private topology Draft Clone; compiler error, Cargo101, no tests. The already-failed compiler was stopped; raw diagnostic retains its process exit code. |
|
||||
| `desktop/focused2*` | Extra guide `explain` argument; compiler error, Cargo101, no tests, same stopped-failed-compiler policy. |
|
||||
| `desktop/focused3*` | Test called private App method; compiler error, Cargo101, no tests. Corrected to the actual Message route. |
|
||||
| `desktop/focused4*` | Successful contextual-source22/22, 2.04s; frozen input manifest and terminal status. |
|
||||
| `desktop/tests-verified/` | Root's full675/675, 448.33s test duration, plus exact executable identity `6E677F58...BE38CC0`. This is the earlier snapshot. |
|
||||
| `desktop/clippy1*` | Completed strict-lint failure on three constant-event `then` expressions; later corrected to `then_some`. |
|
||||
| `desktop/focused5*` | Final contextual-source23/23, 0.98s. The seven-file delta adds the captured document/exact owner recovery regression and narrow guide/lint corrections. Both dated input manifests are retained (about44KB each) because their metadata and hashes bind different executions. |
|
||||
| `desktop/guide-final*` | Final guide3/3, 0.20s. |
|
||||
| `desktop/clippy2*` | Final all-target strict Clippy with warnings denied, PASS, 4m29s. |
|
||||
| `desktop/gui-final*` | Matching final Windows GUI build PASS, 6m20s. |
|
||||
| `desktop/fmt-final-status.json` | Workspace formatting PASS. The original runner produced no `fmt-final.log` file because there was no output; no substitute log was fabricated. |
|
||||
| `desktop/tests-final/manifest.json` | Final test executable `405577A3...626F38`, inventory676; affected23 and guide3 were executed. |
|
||||
| `desktop/gui-verified/manifest.json` | Final GUI `52DE82E4...246ACCE`, with runtime identity. Native acceptance is a separate root task. |
|
||||
|
||||
**There is no full final676 pass in this evidence.** The earlier full675 result must not be relabeled as execution of the later binary. Input manifests identify source-file hashes and contemporaneous Git context, not a claim that uncommitted desktop changes were contained in the listed commit or that every external build input was archived.
|
||||
|
||||
The original `run-final-gates.ps1` and `stage-final.ps1` are preserved as raw records. They document serialized commands, failure stops, unchanged-input checks and refusal to overwrite frozen artifacts. They assume repository cwd, the task-local Windows toolchain and private output paths; they were not run from this archive. Any future rerun needs an explicitly coordinated compiler slot and fresh output paths, and produces new evidence rather than replacing these records.
|
||||
|
||||
## Independent oracle preparation
|
||||
|
||||
`oracle-preparation/manifest.json` binds the independently authored evaluator, fixed two-file baseline, designated core rlib and executable. `build-initial.log` is an actual zero-byte successful diagnostics log, accompanied by its exit/time JSON. Self-check and baseline logs/status passed. The small CLI baseline check records admission with expected warnings, without source writes. These records establish evaluator preparation and falsifier execution, not acceptance of GUI-produced staged-source objects. The already-owned oracle source, fixture and report remain at `harness/staged-source-authoring-contract.rs`, `harness/fixtures/staged-source-authoring/` and `harness/release-staged-source-authoring-oracle-20260911.md`; they are not duplicated here.
|
||||
|
||||
`source-freeze-readback.json` is a new preservation-time check: all13 desktop source hashes matched the final focused5 snapshot. The implementation and independent-review reports remain outside this directory and were not edited by this task.
|
||||
|
||||
To verify this archive without running any application, from this directory:
|
||||
|
||||
```powershell
|
||||
$inventory = Get-Content -LiteralPath inventory.json -Raw | ConvertFrom-Json
|
||||
foreach ($entry in $inventory.files) {
|
||||
$file = Get-Item -LiteralPath $entry.path
|
||||
if ($file.Length -ne $entry.bytes -or
|
||||
(Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash -ne $entry.sha256) {
|
||||
throw "Evidence mismatch: $($entry.path)"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"started": "2026-09-11T12:02:24.4104250Z",
|
||||
"finished": "2026-09-11T12:06:15.0919494Z",
|
||||
"exitCode": 101
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
Checking oa-core v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-core)
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
Compiling oa-server v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-server)
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> crates\oa-desktop\src\behavior\scenario\workspace.rs:199:65
|
||||
|
|
||||
199 | button("Add first lifeline").on_press_maybe(clean.then(|| {
|
||||
| _________________________________________________________________^
|
||||
200 | | Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Lifeline))
|
||||
201 | | }))
|
||||
| |______________________^
|
||||
|
|
||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#unnecessary_lazy_evaluations
|
||||
= note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
|
||||
help: use `then_some` instead
|
||||
|
|
||||
199 ~ button("Add first lifeline").on_press_maybe(clean.then_some({
|
||||
200 + Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Lifeline))
|
||||
201 ~ }))
|
||||
|
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> crates\oa-desktop\src\behavior\scenario\workspace.rs:209:64
|
||||
|
|
||||
209 | button("Add first message").on_press_maybe(clean.then(|| {
|
||||
| ________________________________________________________________^
|
||||
210 | | Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Message))
|
||||
211 | | })),
|
||||
| |______________________^
|
||||
|
|
||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#unnecessary_lazy_evaluations
|
||||
help: use `then_some` instead
|
||||
|
|
||||
209 ~ button("Add first message").on_press_maybe(clean.then_some({
|
||||
210 + Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Message))
|
||||
211 ~ })),
|
||||
|
|
||||
|
||||
error: unnecessary closure used with `bool::then`
|
||||
--> crates\oa-desktop\src\behavior\scenario\workspace.rs:212:63
|
||||
|
|
||||
212 | button("Add first action").on_press_maybe(clean.then(|| {
|
||||
| _______________________________________________________________^
|
||||
213 | | Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Action))
|
||||
214 | | }))
|
||||
| |______________________^
|
||||
|
|
||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#unnecessary_lazy_evaluations
|
||||
help: use `then_some` instead
|
||||
|
|
||||
212 ~ button("Add first action").on_press_maybe(clean.then_some({
|
||||
213 + Message::ScenarioCanvas(CanvasEvent::First(context, Tool::Action))
|
||||
214 ~ }))
|
||||
|
|
||||
|
||||
error: could not compile `oa-desktop` (bin "arcadia-studio" test) due to 3 previous errors
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"started": "2026-09-11T12:25:20.3859405Z",
|
||||
"finished": "2026-09-11T12:29:50.4525461Z",
|
||||
"exitCode": 0,
|
||||
"args": [
|
||||
"clippy",
|
||||
"--locked",
|
||||
"-p",
|
||||
"oa-desktop",
|
||||
"--all-targets",
|
||||
"--",
|
||||
"-D",
|
||||
"warnings"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Checking oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
Finished `dev` profile [unoptimized] target(s) in 4m 29s
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"started": "2026-09-11T12:36:12.8744967Z",
|
||||
"finished": "2026-09-11T12:36:41.0827202Z",
|
||||
"exitCode": 0,
|
||||
"args": [
|
||||
"fmt",
|
||||
"--all",
|
||||
"--",
|
||||
"--check"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"finished": "2026-09-11T11:27:02.1571291Z",
|
||||
"started": "2026-09-11T11:23:44.5463460Z",
|
||||
"exitCode": 101
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
error[E0308]: mismatched types
|
||||
--> crates\oa-desktop\src\behavior\topology.rs:197:31
|
||||
|
|
||||
197 | self.draft = Some(next);
|
||||
| ---- ^^^^ expected `Draft`, found `&Draft`
|
||||
| |
|
||||
| arguments to this enum variant are incorrect
|
||||
|
|
||||
note: `behavior::topology::Draft` does not implement `Clone`, so `&behavior::topology::Draft` was cloned instead
|
||||
--> crates\oa-desktop\src\behavior\topology.rs:187:28
|
||||
|
|
||||
187 | let mut next = d.clone();
|
||||
| ^
|
||||
help: the type constructed contains `&behavior::topology::Draft` due to the type of the argument passed
|
||||
--> crates\oa-desktop\src\behavior\topology.rs:197:26
|
||||
|
|
||||
197 | self.draft = Some(next);
|
||||
| ^^^^^----^
|
||||
| |
|
||||
| this argument influences the type of `Some`
|
||||
note: tuple variant defined here
|
||||
--> /rustc/48a229ceaefd4985c50990b14116b6d856af0985/library\core\src\option.rs:606:4
|
||||
help: consider annotating `behavior::topology::Draft` with `#[derive(Clone)]`
|
||||
|
|
||||
102 + #[derive(Clone)]
|
||||
103 | struct Draft {
|
||||
|
|
||||
|
||||
error: could not compile `oa-desktop` (bin "arcadia-studio" test) due to 1 previous error
|
||||
|
||||
Caused by:
|
||||
process didn't exit successfully: `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\rustup\toolchains\stable-x86_64-pc-windows-gnullvm\bin\rustc.exe --crate-name arcadia_studio --edition=2024 crates\oa-desktop\src\main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --emit=dep-info,link -C embed-bitcode=no --test --check-cfg cfg(docsrs,test) --check-cfg "cfg(feature, values())" -C metadata=e92d7ab29d07ce2a -C extra-filename=-58e30cee1fd51a8b --out-dir C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps -C linker=clang.exe -C incremental=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\incremental -C strip=debuginfo -L dependency=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps --extern axum=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libaxum-ccc7aea466db9258.rlib --extern iced=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced-ee73abd722c72024.rlib --extern iced_runtime=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced_runtime-97354eb606c5cbe8.rlib --extern oa_core=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_core-6c8da57367eec642.rlib --extern oa_server=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_server-69305e51c40cee45.rlib --extern reqwest=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libreqwest-31ac987472fa8038.rlib --extern rfd=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\librfd-17cc7ba2db223d7b.rlib --extern serde=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde-60a32311146a42e4.rlib --extern serde_json=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde_json-da2c4f333fc47818.rlib --extern tempfile=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtempfile-86aac28d6be16d2f.rlib --extern tokio=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtokio-5e0ca96735e3073a.rlib -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\ring-5f8d2d20440f09b4\out -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\cargo\registry\src\index.crates.io-1949cf8c6b5b557f\windows_x86_64_gnullvm-0.52.6\lib -C link-arg=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\oa-desktop-664d65ac5124e646\out\normal-user-manifest.o` (exit code: 0xffffffff)
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"finished": "2026-09-11T11:39:43.0079347Z",
|
||||
"started": "2026-09-11T11:37:10.5178164Z",
|
||||
"exitCode": 101
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
|
||||
--> crates\oa-desktop\src\guide.rs:899:25
|
||||
|
|
||||
899 | ... explain(
|
||||
| ^^^^^^^
|
||||
...
|
||||
902 | ... "Behavior → New keeps the exact name, owner ...d raw text, for correction or cancellation.",
|
||||
| --------------------------------------------...-------------------------------------------- unexpected argument #3 of type `&'static str`
|
||||
|
|
||||
note: function defined here
|
||||
--> crates\oa-desktop\src\guide.rs:150:10
|
||||
|
|
||||
150 | const fn explain(title: &'static str, body: &'static str) -> Section {
|
||||
| ^^^^^^^
|
||||
help: remove the extra argument
|
||||
|
|
||||
901 - "Inside a source subform, Back or the first Escape returns to the unchanged parent. Use this new source stages the prerequisite only. Canceling the parent discards it; choosing an existing reference excludes the staged source from creation. Recovery retains both forms and their reserved identities. An open dialog still receives Escape first.",
|
||||
902 - "Behavior → New keeps the exact name, owner and viewpoint choices outside the model until Create and open succeeds. Cancel or Escape discards only this draft; if a dialog is open, the first Escape dismisses that dialog. New refuses other unfinished property, source or behavior drafts without applying them. Recovery restores the creation form in its original layer, including rejected raw text, for correction or cancellation.",
|
||||
901 + "Inside a source subform, Back or the first Escape returns to the unchanged parent. Use this new source stages the prerequisite only. Canceling the parent discards it; choosing an existing reference excludes the staged source from creation. Recovery retains both forms and their reserved identities. An open dialog still receives Escape first.",
|
||||
|
|
||||
|
||||
error: could not compile `oa-desktop` (bin "arcadia-studio" test) due to 1 previous error
|
||||
|
||||
Caused by:
|
||||
process didn't exit successfully: `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\rustup\toolchains\stable-x86_64-pc-windows-gnullvm\bin\rustc.exe --crate-name arcadia_studio --edition=2024 crates\oa-desktop\src\main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --emit=dep-info,link -C embed-bitcode=no --test --check-cfg cfg(docsrs,test) --check-cfg "cfg(feature, values())" -C metadata=e92d7ab29d07ce2a -C extra-filename=-58e30cee1fd51a8b --out-dir C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps -C linker=clang.exe -C incremental=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\incremental -C strip=debuginfo -L dependency=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps --extern axum=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libaxum-ccc7aea466db9258.rlib --extern iced=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced-ee73abd722c72024.rlib --extern iced_runtime=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced_runtime-97354eb606c5cbe8.rlib --extern oa_core=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_core-6c8da57367eec642.rlib --extern oa_server=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_server-69305e51c40cee45.rlib --extern reqwest=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libreqwest-31ac987472fa8038.rlib --extern rfd=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\librfd-17cc7ba2db223d7b.rlib --extern serde=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde-60a32311146a42e4.rlib --extern serde_json=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde_json-da2c4f333fc47818.rlib --extern tempfile=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtempfile-86aac28d6be16d2f.rlib --extern tokio=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtokio-5e0ca96735e3073a.rlib -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\ring-5f8d2d20440f09b4\out -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\cargo\registry\src\index.crates.io-1949cf8c6b5b557f\windows_x86_64_gnullvm-0.52.6\lib -C link-arg=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\oa-desktop-664d65ac5124e646\out\normal-user-manifest.o` (exit code: 0xffffffff)
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"started": "2026-09-11T11:48:07.8443256Z",
|
||||
"exitCode": 101,
|
||||
"finished": "2026-09-11T11:49:20.9876952Z"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
error[E0624]: method `execute` is private
|
||||
--> crates\oa-desktop\src\behavior\contextual_source_tests.rs:1112:17
|
||||
|
|
||||
1112 | assert!(app.execute(Command::Rename(owner, "Accepted renamed scenario".into())));
|
||||
| ^^^^^^^ private method
|
||||
|
|
||||
::: crates\oa-desktop\src\app.rs:851:5
|
||||
|
|
||||
851 | fn execute(&mut self, command: Command) -> bool {
|
||||
| ----------------------------------------------- private method defined here
|
||||
|
||||
error: could not compile `oa-desktop` (bin "arcadia-studio" test) due to 1 previous error
|
||||
|
||||
Caused by:
|
||||
process didn't exit successfully: `C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\rustup\toolchains\stable-x86_64-pc-windows-gnullvm\bin\rustc.exe --crate-name arcadia_studio --edition=2024 crates\oa-desktop\src\main.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --emit=dep-info,link -C embed-bitcode=no --test --check-cfg cfg(docsrs,test) --check-cfg "cfg(feature, values())" -C metadata=e92d7ab29d07ce2a -C extra-filename=-58e30cee1fd51a8b --out-dir C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps -C linker=clang.exe -C incremental=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\incremental -C strip=debuginfo -L dependency=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps --extern axum=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libaxum-ccc7aea466db9258.rlib --extern iced=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced-ee73abd722c72024.rlib --extern iced_runtime=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libiced_runtime-97354eb606c5cbe8.rlib --extern oa_core=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_core-6c8da57367eec642.rlib --extern oa_server=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\liboa_server-69305e51c40cee45.rlib --extern reqwest=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libreqwest-31ac987472fa8038.rlib --extern rfd=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\librfd-17cc7ba2db223d7b.rlib --extern serde=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde-60a32311146a42e4.rlib --extern serde_json=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libserde_json-da2c4f333fc47818.rlib --extern tempfile=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtempfile-86aac28d6be16d2f.rlib --extern tokio=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\deps\libtokio-5e0ca96735e3073a.rlib -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\ring-5f8d2d20440f09b4\out -L native=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\cargo\registry\src\index.crates.io-1949cf8c6b5b557f\windows_x86_64_gnullvm-0.52.6\lib -C link-arg=C:\Users\User\Documents\Git\ARCADIA-Studio\.local\target-gnullvm\debug\build\oa-desktop-664d65ac5124e646\out\normal-user-manifest.o` (exit code: 0xffffffff)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"exitCode": 0,
|
||||
"finished": "2026-09-11T11:59:25.8739914Z",
|
||||
"started": "2026-09-11T11:49:26.5831603Z"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
Finished `test` profile [unoptimized] target(s) in 9m 56s
|
||||
Running unittests src\main.rs (.local\target-gnullvm\debug\deps\arcadia_studio-58e30cee1fd51a8b.exe)
|
||||
|
||||
running 22 tests
|
||||
test behavior::contextual_source_tests::contextual_source_app_checkpoint_restores_inner_raw_draft_without_model_adoption ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_empty_actions_and_child_open_refuse_other_raw_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_modal_escape_then_child_back_then_parent_cancel_preserve_accepted_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_remains_available_after_owner_deletion_and_with_dirty_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_retains_parent_and_rejects_late_child_event ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_default_consumer_name_has_stable_alias_and_correlated_selection ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_deleted_owner_view_retains_draft_instead_of_panicking_or_using_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_empty_history_reports_no_change_and_success_requires_a_real_history_step ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_existing_choice_prunes_staged_dependency ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_failed_source_budget_preserves_both_drafts_and_accepted_bytes ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_incomplete_recovered_kind_reports_error_without_panicking ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_inserts_work_on_the_exact_guarded_link_and_refuses_exchange_identity_conflict ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_lifelines_stage_exact_separate_records_and_one_history_entry ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_machine_before_any_owner_creates_optional_view_atomically ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_mounted_small_editor_keeps_back_and_use_outside_field_scroll ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_nested_semantic_parent_is_explicit_and_revalidated ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_new_callee_lifeline_preserves_caller_bindings_as_an_explicit_warning ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_old_empty_action_cannot_open_a_previous_owner_or_layer ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_owner_first_can_return_to_an_unnamed_machine_without_losing_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_recovery_keeps_inner_raw_fields_and_refuses_deleted_or_changed_owner ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_second_system_and_role_machine_owner_refuse_without_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_work_uses_reserved_contribution_and_link_ids_and_one_undo ... ok
|
||||
|
||||
test result: ok. 22 passed; 0 failed; 0 ignored; 0 measured; 653 filtered out; finished in 2.04s
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\contextual_source_tests.rs",
|
||||
"before": "42E3E985EBA327B518D731AE0714AD5F9B48AF991E9FD62B2B0666E139E02487",
|
||||
"after": "5F05318A6533503B9D6FEBF1EC4DD7256F192394BC1B952A7904C8175BD8DDAE"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\creation.rs",
|
||||
"before": "AB851BCBC3EB070D5911F878EE43FE0530FCB67269103B4B56EF73E17F5BC104",
|
||||
"after": "CA7275B5C0118CBB78F5D16254E50FADDC26DBB53816D01950064C852E296B2E"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\scenario.rs",
|
||||
"before": "5ED3FD63433EF51A6D6315FC4F8251995BBCAA29A0A938FAC0921A4845FAAB2A",
|
||||
"after": "D12A4B1CAA61C08F69C4D2A64BD15568C4B7158DEA91AAC5A52A58A35ADB863C"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\scenario\\workspace.rs",
|
||||
"before": "6100D1A6CE09CD3C2836EB1559DADF382437DB34DB2BDA76CEB4E479CB15DA41",
|
||||
"after": "69C7AD32E4BDC39F42D2E6C7764CFE1FA7867CD7DBCF9B904DEC805E6C912666"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\source_draft.rs",
|
||||
"before": "7447D38E178C3B199901E519ABDCA6868CFD52510F7B67A5EA8B849072CDAE2D",
|
||||
"after": "68F396C420FFF132FF0EAB82CB2C6251477412F6F9F90AD2E76C51A259F8A69A"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\behavior\\topology.rs",
|
||||
"before": "40139E3714E702E1F331F98EE2579E167D3CA61330864772EC5E40614F118A5A",
|
||||
"after": "D06B2F0FC39B4814E94200297E148F1D4D97E04CB167766030AC9DF18689E3B0"
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop\\src\\guide.rs",
|
||||
"before": "C6425F2FBC2D7D04015E15D78F602CA838019B7C15352EF5A380F78A30800C68",
|
||||
"after": "47EEB3CC0A48D5712720096015A08387CD354FB91559B0BD6FA106B5CAC6292C"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"started": "2026-09-11T12:20:22.2107248Z",
|
||||
"finished": "2026-09-11T12:25:14.9560639Z",
|
||||
"exitCode": 0,
|
||||
"args": [
|
||||
"test",
|
||||
"--locked",
|
||||
"-p",
|
||||
"oa-desktop",
|
||||
"--bin",
|
||||
"arcadia-studio",
|
||||
"contextual_source",
|
||||
"--",
|
||||
"--test-threads=1"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
Finished `test` profile [unoptimized] target(s) in 4m 48s
|
||||
Running unittests src\main.rs (.local\target-gnullvm\debug\deps\arcadia_studio-58e30cee1fd51a8b.exe)
|
||||
|
||||
running 23 tests
|
||||
test behavior::contextual_source_tests::contextual_source_app_checkpoint_restores_inner_raw_draft_without_model_adoption ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_empty_actions_and_child_open_refuse_other_raw_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_modal_escape_then_child_back_then_parent_cancel_preserve_accepted_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_remains_available_after_owner_deletion_and_with_dirty_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_retains_parent_and_rejects_late_child_event ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_default_consumer_name_has_stable_alias_and_correlated_selection ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_deleted_owner_view_retains_draft_instead_of_panicking_or_using_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_empty_history_reports_no_change_and_success_requires_a_real_history_step ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_existing_choice_prunes_staged_dependency ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_failed_source_budget_preserves_both_drafts_and_accepted_bytes ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_incomplete_recovered_kind_reports_error_without_panicking ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_inserts_work_on_the_exact_guarded_link_and_refuses_exchange_identity_conflict ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_lifelines_stage_exact_separate_records_and_one_history_entry ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_machine_before_any_owner_creates_optional_view_atomically ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_mounted_small_editor_keeps_back_and_use_outside_field_scroll ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_nested_semantic_parent_is_explicit_and_revalidated ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_new_callee_lifeline_preserves_caller_bindings_as_an_explicit_warning ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_old_empty_action_cannot_open_a_previous_owner_or_layer ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_original_document_remains_bound_after_back_or_choosing_existing ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_owner_first_can_return_to_an_unnamed_machine_without_losing_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_recovery_keeps_inner_raw_fields_and_refuses_deleted_or_changed_owner ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_second_system_and_role_machine_owner_refuse_without_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_work_uses_reserved_contribution_and_link_ids_and_one_undo ... ok
|
||||
|
||||
test result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 653 filtered out; finished in 0.98s
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"started": "2026-09-11T12:29:50.4564653Z",
|
||||
"finished": "2026-09-11T12:36:12.8525359Z",
|
||||
"exitCode": 0,
|
||||
"args": [
|
||||
"build",
|
||||
"--locked",
|
||||
"-p",
|
||||
"oa-desktop",
|
||||
"--bin",
|
||||
"arcadia-studio"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
Compiling oa-desktop v0.2.0 (C:\Users\User\Documents\Git\ARCADIA-Studio\crates\oa-desktop)
|
||||
Finished `dev` profile [unoptimized] target(s) in 6m 20s
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"created": "2026-09-11T12:37:04.6742598Z",
|
||||
"scope": "Final matching Windows GUI build, strictClippy and formatting passed; native acceptance pending root",
|
||||
"sourceInputs": "../focused5-inputs.json",
|
||||
"sourceDeltaFromFull675": "../focused5-delta.json",
|
||||
"artifacts": [
|
||||
{
|
||||
"file": "arcadia-studio.exe",
|
||||
"sha256": "52DE82E434B636E18DB02D381842AA6DB84B721CFFD5502063F784F37246ACCE",
|
||||
"bytes": 112219136
|
||||
},
|
||||
{
|
||||
"file": "libunwind.dll",
|
||||
"sha256": "F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4",
|
||||
"bytes": 190976
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"started": "2026-09-11T12:25:15.0326187Z",
|
||||
"finished": "2026-09-11T12:25:20.3798172Z",
|
||||
"exitCode": 0,
|
||||
"args": [
|
||||
"test",
|
||||
"--locked",
|
||||
"-p",
|
||||
"oa-desktop",
|
||||
"--bin",
|
||||
"arcadia-studio",
|
||||
"guide",
|
||||
"--",
|
||||
"--test-threads=1"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
Finished `test` profile [unoptimized] target(s) in 4.40s
|
||||
Running unittests src\main.rs (.local\target-gnullvm\debug\deps\arcadia_studio-58e30cee1fd51a8b.exe)
|
||||
|
||||
running 3 tests
|
||||
test guide::tests::filtering_and_related_navigation_keep_selection_visible ... ok
|
||||
test guide::tests::guide_topic_navigation_resets_only_article_and_same_topic_search_keeps_scroll ... ok
|
||||
test guide::tests::search_finds_concepts_in_walkthroughs_and_api_reference ... ok
|
||||
|
||||
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 673 filtered out; finished in 0.20s
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
. ./.local/toolchain/env.ps1
|
||||
$env:CARGO_BUILD_JOBS = '1'
|
||||
$evidenceRoot = Join-Path (Get-Location) '.local/contextual-source-20260911'
|
||||
$gates = @(
|
||||
@{name='focused5'; args=@('test','--locked','-p','oa-desktop','--bin','arcadia-studio','contextual_source','--','--test-threads=1')},
|
||||
@{name='guide-final'; args=@('test','--locked','-p','oa-desktop','--bin','arcadia-studio','guide','--','--test-threads=1')},
|
||||
@{name='clippy2'; args=@('clippy','--locked','-p','oa-desktop','--all-targets','--','-D','warnings')},
|
||||
@{name='gui-final'; args=@('build','--locked','-p','oa-desktop','--bin','arcadia-studio')},
|
||||
@{name='fmt-final'; args=@('fmt','--all','--','--check')}
|
||||
)
|
||||
foreach ($gate in $gates) {
|
||||
$logPath = Join-Path $evidenceRoot ($gate.name + '.log')
|
||||
$statusPath = Join-Path $evidenceRoot ($gate.name + '-status.json')
|
||||
if ((Test-Path -LiteralPath $logPath) -or (Test-Path -LiteralPath $statusPath)) { throw "Refusing to overwrite $($gate.name)" }
|
||||
$started = [DateTime]::UtcNow.ToString('o')
|
||||
$gateArgs = $gate.args
|
||||
& cargo @gateArgs 2>&1 | Tee-Object -FilePath $logPath
|
||||
$gateExit = $LASTEXITCODE
|
||||
[ordered]@{started=$started;finished=[DateTime]::UtcNow.ToString('o');exitCode=$gateExit;args=$gateArgs} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath $statusPath
|
||||
if ($gateExit -ne 0) { exit $gateExit }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$evidenceRoot = Join-Path (Get-Location) '.local/contextual-source-20260911'
|
||||
foreach ($gate in 'focused5','guide-final','clippy2','gui-final','fmt-final') {
|
||||
$status = Get-Content -LiteralPath (Join-Path $evidenceRoot ($gate + '-status.json')) -Raw | ConvertFrom-Json
|
||||
if ($status.exitCode -ne 0) { throw "$gate has not passed" }
|
||||
}
|
||||
$inputs = Get-Content -LiteralPath (Join-Path $evidenceRoot 'focused5-inputs.json') -Raw | ConvertFrom-Json
|
||||
foreach ($inputFile in $inputs.inputs) {
|
||||
if ((Get-FileHash -LiteralPath $inputFile.path -Algorithm SHA256).Hash -ne $inputFile.sha256) { throw "Input changed: $($inputFile.path)" }
|
||||
}
|
||||
$testLog = Get-Content -LiteralPath (Join-Path $evidenceRoot 'focused5.log') -Raw
|
||||
if ($testLog -notmatch 'Running unittests[^\r\n]+\(([^\r\n]+\.exe)\)') { throw 'No executed test binary in focused5 log' }
|
||||
$testPath = $Matches[1]
|
||||
$runtimePath = Join-Path $evidenceRoot 'tests-verified/libunwind.dll'
|
||||
if ((Get-FileHash -LiteralPath $runtimePath -Algorithm SHA256).Hash -ne 'F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4') { throw 'Runtime hash mismatch' }
|
||||
$stages = @(
|
||||
@{directory='tests-final';source=$testPath;name='arcadia-studio-tests.exe';scope='Final affected contextual-source and guide tests; broader full675 belongs to earlier tests-verified snapshot'},
|
||||
@{directory='gui-verified';source='.local/target-gnullvm/debug/arcadia-studio.exe';name='arcadia-studio.exe';scope='Final matching Windows GUI build, strictClippy and formatting passed; native acceptance pending root'}
|
||||
)
|
||||
foreach ($stage in $stages) {
|
||||
$destination = Join-Path $evidenceRoot $stage.directory
|
||||
if (Test-Path -LiteralPath $destination) { throw "Refusing to overwrite $destination" }
|
||||
New-Item -ItemType Directory -Path $destination | Out-Null
|
||||
Copy-Item -LiteralPath $stage.source -Destination (Join-Path $destination $stage.name)
|
||||
Copy-Item -LiteralPath $runtimePath -Destination (Join-Path $destination 'libunwind.dll')
|
||||
$artifacts = foreach ($filename in $stage.name,'libunwind.dll') {
|
||||
$item = Get-Item -LiteralPath (Join-Path $destination $filename)
|
||||
[ordered]@{file=$filename;sha256=(Get-FileHash -LiteralPath $item.FullName -Algorithm SHA256).Hash;bytes=$item.Length}
|
||||
}
|
||||
[ordered]@{created=[DateTime]::UtcNow.ToString('o');scope=$stage.scope;sourceInputs='../focused5-inputs.json';sourceDeltaFromFull675='../focused5-delta.json';artifacts=@($artifacts)} | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $destination 'manifest.json')
|
||||
Get-Content -LiteralPath (Join-Path $destination 'manifest.json') -Raw
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"created": "2026-09-11T12:37:00.9856183Z",
|
||||
"scope": "Final affected contextual-source and guide tests; broader full675 belongs to earlier tests-verified snapshot",
|
||||
"sourceInputs": "../focused5-inputs.json",
|
||||
"sourceDeltaFromFull675": "../focused5-delta.json",
|
||||
"artifacts": [
|
||||
{
|
||||
"file": "arcadia-studio-tests.exe",
|
||||
"sha256": "405577A35CE643AC022885AF58706D6F8B321224AE6D68E2555FBFAF3D626F38",
|
||||
"bytes": 107101696
|
||||
},
|
||||
{
|
||||
"file": "libunwind.dll",
|
||||
"sha256": "F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4",
|
||||
"bytes": 190976
|
||||
}
|
||||
]
|
||||
}
|
||||
+680
@@ -0,0 +1,680 @@
|
||||
|
||||
running 675 tests
|
||||
test app::architecture_authoring::tests::architecture_allocated_work_is_root_owned_and_one_exact_history_change ... ok
|
||||
test app::architecture_authoring::tests::architecture_blank_names_and_escape_never_accept_placeholder_or_rename ... ok
|
||||
test app::architecture_authoring::tests::architecture_captured_escape_does_not_cancel_other_controls_or_placement ... ok
|
||||
test app::architecture_authoring::tests::architecture_f2_routes_selected_node_to_inline_rename_and_exact_undo ... ok
|
||||
test app::architecture_authoring::tests::architecture_first_focused_input_escape_cancels_create_and_rename ... ok
|
||||
test app::architecture_authoring::tests::architecture_invalid_click_cannot_poison_inline_or_checkpoint_geometry ... ok
|
||||
test app::architecture_authoring::tests::architecture_stale_submit_keeps_create_and_rename_visible_and_exact ... ok
|
||||
test app::architecture_authoring_tests::architecture_cancelled_gesture_cannot_commit_a_later_named_draft ... ok
|
||||
test app::architecture_authoring_tests::architecture_canvas_left_click_uses_world_coordinate_once_at_zoom_and_pan ... ok
|
||||
test app::architecture_authoring_tests::architecture_checkpoint_retains_exact_name_point_and_fresh_binding_without_commands ... ok
|
||||
test app::architecture_authoring_tests::architecture_context_choices_are_small_and_system_is_singleton ... ok
|
||||
test app::architecture_authoring_tests::architecture_contextual_allocation_creates_work_relation_and_node_in_one_undo ... ok
|
||||
test app::architecture_authoring_tests::architecture_creation_names_before_commit_preserves_camera_and_undoes_once ... ok
|
||||
test app::architecture_authoring_tests::architecture_existing_inventory_is_contextual_and_placement_never_implies_allocation ... ok
|
||||
test app::architecture_authoring_tests::architecture_f2_rename_preserves_identity_placement_and_atomic_history ... ok
|
||||
test app::architecture_authoring_tests::architecture_name_survives_rejected_click_resize_navigation_and_escape_is_explicit ... ok
|
||||
test app::architecture_authoring_tests::architecture_rejected_submission_keeps_inline_name_visible_and_invalid_click_is_ignored ... ok
|
||||
test app::architecture_authoring_tests::basic_transition_explicit_overview_focus_wins_over_an_already_populated_architecture ... ok
|
||||
test app::behavior_lifecycle_tests::incomplete_behavior_form_is_dirty_close_save_retains_it_and_cancel_allows_switching ... ok
|
||||
test app::behavior_lifecycle_tests::passive_behavior_canvas_events_do_not_apply_property_drafts ... ok
|
||||
test app::behavior_lifecycle_tests::pending_behavior_blocks_navigation_property_edits_and_model_history ... ok
|
||||
test app::behavior_lifecycle_tests::pending_behavior_blocks_source_creation_and_source_history_replay ... ok
|
||||
test app::behavior_lifecycle_tests::save_prepares_behavior_before_opening_destination_and_cancel_keeps_one_undo ... ok
|
||||
test app::behavior_lifecycle_tests::source_writeback_failure_keeps_typed_behavior_form_for_repair_and_one_undo ... ok
|
||||
test app::checkpoints::tests::checkpoint_completion_releases_the_writer_while_a_context_menu_is_open ... ok
|
||||
test app::checkpoints::tests::checkpoint_inline_create_and_rename_restore_focus_without_changing_drafts_or_history ... ok
|
||||
test app::checkpoints::tests::checkpoint_noninline_contexts_keep_other_focus_and_still_lint ... ok
|
||||
test app::checkpoints::tests::discard_and_close_waits_for_the_late_checkpoint_then_retires_it ... ok
|
||||
test app::checkpoints::tests::home_resume_keeps_state_view_while_explicit_architecture_remains_reachable ... ok
|
||||
test app::checkpoints::tests::home_resume_retains_invalid_source_and_property_drafts ... ok
|
||||
test app::checkpoints::tests::home_resume_returns_to_each_actual_workspace_without_model_edits ... ok
|
||||
test app::checkpoints::tests::malformed_checkpoint_does_not_replace_the_current_model ... ok
|
||||
test app::checkpoints::tests::recent_and_recovery_navigation_respect_unsaved_decision ... ok
|
||||
test app::checkpoints::tests::restored_copy_keeps_raw_property_and_requires_save_without_local_or_hosted_binding ... ok
|
||||
test app::checkpoints::tests::saving_an_older_snapshot_keeps_recovery_for_newer_unsaved_work ... ok
|
||||
test app::checkpoints::tests::stale_write_completion_cannot_recover_a_discarded_document ... ok
|
||||
test app::checkpoints::tests::walkthrough_request_keeps_unfinished_source_behind_the_normal_pending_guard ... ok
|
||||
test app::data_paging_lifecycle_tests::paging_preserves_same_context_and_resets_on_layer_or_document_replacement ... ok
|
||||
test app::diagram_selection_tests::changing_visible_view_follows_its_clean_inspector_without_a_model_edit ... ok
|
||||
test app::diagram_selection_tests::diagram_switch_preserves_an_independent_semantic_inspection ... ok
|
||||
test app::diagram_selection_tests::diagram_uuid_edit_follows_the_same_view_or_a_different_picker_target ... ok
|
||||
test app::diagram_selection_tests::invalid_view_draft_blocks_the_switch_and_retains_raw_input ... ok
|
||||
test app::diagram_selection_tests::stale_diagram_choice_never_applies_an_unrelated_valid_draft ... ok
|
||||
test app::diagram_selection_tests::valid_pending_view_edit_applies_to_old_view_then_inspects_the_new_view ... ok
|
||||
test app::direct_scenario_tests::direct_scenario_creation_and_reorder_preserve_selection_and_each_undo_once ... ok
|
||||
test app::direct_scenario_tests::direct_scenario_rejects_every_stale_context_and_preserves_property_drafts ... ok
|
||||
test app::direct_scenario_tests::direct_scenario_scroll_and_real_resize_invalidate_only_pointer_context ... ok
|
||||
test app::direct_scenario_tests::direct_scenario_source_failure_and_navigation_keep_form_until_success ... ok
|
||||
test app::hosted::tests::hosted_actual_app_tasks_publish_edit_conflict_correct_credentials_reload_and_open ... ok
|
||||
test app::hosted::tests::hosted_catalog_invalidation_follows_service_writes_and_observed_revision_changes ... ok
|
||||
test app::hosted::tests::hosted_catalog_search_credentials_and_failed_refresh_never_mix_result_scopes ... ok
|
||||
test app::hosted::tests::hosted_changed_bound_head_does_not_invalidate_another_services_empty_filter ... ok
|
||||
test app::hosted::tests::hosted_conflict_fetches_review_without_adoption_and_reload_is_undoable ... ok
|
||||
test app::hosted::tests::hosted_detached_drafts_and_recovery_remain_available_after_rejected_publish ... ok
|
||||
test app::hosted::tests::hosted_failed_cross_service_publication_checks_and_reloads_its_own_resource ... ok
|
||||
test app::hosted::tests::hosted_failed_or_cancelled_local_open_keeps_the_existing_document_and_destination ... ok
|
||||
test app::hosted::tests::hosted_invalid_and_detached_source_drafts_never_start_network_writes ... ok
|
||||
test app::hosted::tests::hosted_invalid_local_open_repair_saves_locally_and_never_replaces_old_resource ... ok
|
||||
test app::hosted::tests::hosted_modal_blocks_underlying_edits_and_credentials_are_redacted ... ok
|
||||
test app::hosted::tests::hosted_new_revision_invalidates_filtered_catalog_even_without_a_displayed_row ... ok
|
||||
test app::hosted::tests::hosted_only_successful_source_save_as_changes_the_active_destination ... ok
|
||||
test app::hosted::tests::hosted_open_waits_for_unsaved_guard_and_failed_open_preserves_current_document ... ok
|
||||
test app::hosted::tests::hosted_publish_acknowledges_only_the_sent_snapshot_and_retains_undo ... ok
|
||||
test app::hosted::tests::hosted_stale_completions_do_not_clear_current_busy_or_adopt_another_document ... ok
|
||||
test app::hosted::tests::hosted_unknown_save_is_acknowledged_by_exact_readback_without_retry ... ok
|
||||
test app::lint_tests::committed_check_cache_follows_edit_and_undo_while_drafts_stay_separate ... ok
|
||||
test app::lint_tests::lint_coalesces_work_and_rejects_obsolete_results ... ok
|
||||
test app::lint_tests::prior_document_lint_cannot_enter_reopened_model_or_block_next_checks ... ok
|
||||
test app::port_view_tests::catalog_creation_follows_the_new_port_and_keeps_group_browsing_explicit ... ok
|
||||
test app::port_view_tests::filtered_active_view_cannot_hide_a_created_port_when_eligible_owner_view_is_folded ... ok
|
||||
test app::process_canvas::direct_process_dirty_source_blocks_canvas_creation_without_losing_text ... ok
|
||||
test app::process_canvas::tests::direct_process_app_open_source_and_back_preserve_local_reference_identity ... ok
|
||||
test app::process_canvas::tests::direct_process_app_same_owner_selection_preserves_tool_but_owner_change_resets_it ... ok
|
||||
test app::process_canvas::tests::direct_process_app_save_scroll_resize_and_passive_geometry_keep_drafts_and_current_origin ... ok
|
||||
test app::process_canvas::tests::direct_process_app_source_failure_retains_form_then_commits_once_and_selects_occurrence ... ok
|
||||
test app::process_canvas::tests::direct_process_app_stale_context_dirty_source_and_properties_never_mutate ... ok
|
||||
test app::process_canvas::tests::direct_process_append_empty_first_second_exchange_has_exact_source_history ... ok
|
||||
test app::process_canvas::tests::process_focus_retains_rejected_draft_and_guards_selection_until_panels_restore ... ok
|
||||
test app::review_navigation_tests::rejected_semantic_source_writeback_retains_review_camera_and_original_navigation ... ok
|
||||
test app::review_navigation_tests::review_already_showing_the_target_keeps_its_camera_and_query ... ok
|
||||
test app::review_navigation_tests::semantic_name_take_selects_the_counterpart_view_in_both_directions_with_one_exact_history_entry ... ok
|
||||
test app::review_navigation_tests::semantic_review_without_a_destination_view_clears_the_old_layer_canvas_without_creating_a_view ... ok
|
||||
test app::save_as_tests::save_as_late_receipt_preserves_newer_raw_source_draft_and_destination ... ok
|
||||
test app::save_as_tests::save_as_preflight_rejects_historical_collision_before_starting_io ... ok
|
||||
test app::save_as_tests::save_as_receipt_then_one_undo_restores_meaning_and_saving_preserves_redo ... ok
|
||||
test app::source_project_tests::closed_detached_file_keeps_first_save_conflict_then_can_be_reloaded_fresh ... ok
|
||||
test app::source_project_tests::inactive_invalid_draft_blocks_graphical_changes_and_diagnostic_switches_files ... ok
|
||||
test app::source_project_tests::json_export_and_rejected_save_as_preserve_source_location_history_and_bytes ... ok
|
||||
test app::source_project_tests::missing_include_open_keeps_old_model_and_can_be_repaired_and_saved ... ok
|
||||
test app::source_project_tests::recovery_after_first_save_failure_retains_target_then_retries_without_reentering_path ... ok
|
||||
test app::source_project_tests::recovery_of_previous_save_as_target_does_not_redirect_current_project ... ok
|
||||
test app::source_project_tests::recovery_open_finds_first_save_journal_without_an_entry_file ... ok
|
||||
test app::source_project_tests::recovery_target_survives_edit_lint_apply_and_rejected_recovery_until_success ... ok
|
||||
test app::source_project_tests::source3_native_open_preserves_report_comments_nesting_and_save_reopen ... ok
|
||||
test app::source_project_tests::two_file_apply_graphical_edit_exact_undo_save_as_and_reopen ... ok
|
||||
test app::state_diagram_tests::all_context_dimensions_reject_stale_selection_camera_and_model_messages ... ok
|
||||
test app::state_diagram_tests::create_view_places_only_its_machine_and_restores_exact_source_in_one_undo ... ok
|
||||
test app::state_diagram_tests::direct_create_connect_select_and_move_keep_semantic_identity_and_atomic_history ... ok
|
||||
test app::state_diagram_tests::fallback_owner_first_selection_keeps_the_captured_context_for_its_first_move ... ok
|
||||
test app::state_diagram_tests::pending_drafts_block_every_direct_mutation_and_passive_camera_preserves_inputs ... ok
|
||||
test app::state_diagram_tests::real_view_tool_and_history_changes_invalidate_old_release_events ... ok
|
||||
test app::state_diagram_tests::rejected_creation_keeps_source_and_selection_then_valid_owner_can_retry ... ok
|
||||
test app::state_diagram_tests::same_size_viewport_after_revision_or_tool_epoch_does_not_refit_the_camera ... ok
|
||||
test app::state_diagram_tests::shared_semantic_states_keep_architecture_and_behavior_placements_independent ... ok
|
||||
test app::state_diagram_tests::state_diagram_routes_constructor_and_source_open_to_the_existing_workspace_without_edits ... ok
|
||||
test app::state_diagram_tests::state_diagram_routes_picker_and_reveal_but_explicit_architecture_does_not_bounce ... ok
|
||||
test app::state_diagram_tests::state_diagram_routes_preserve_selected_raw_properties_and_pending_behavior_guards ... ok
|
||||
test app::state_diagram_tests::state_navigation_catalog_selection_across_layers_resets_camera_and_tool ... ok
|
||||
test app::state_diagram_tests::state_navigation_catalog_selection_of_another_machine_resets_camera_and_tool ... ok
|
||||
test app::state_diagram_tests::state_navigation_layer_change_resets_the_new_machine_at_the_same_viewport_size ... ok
|
||||
test app::state_diagram_tests::state_navigation_return_to_the_same_view_preserves_camera_tool_and_fit_mode ... ok
|
||||
test app::state_diagram_tests::state_navigation_root_event_and_same_layer_keep_the_current_camera_and_tool ... ok
|
||||
test app::transition_context_tests::explicit_behavior_internal_and_process_roots_keep_their_workspace_without_creating_a_view ... ok
|
||||
test app::transition_context_tests::explicit_destination_is_honored_and_ordinary_work_transition_still_places_in_architecture ... ok
|
||||
test app::transition_context_tests::machine_and_typed_action_transitions_resolve_the_owner_and_reusing_that_context_retains_camera ... ok
|
||||
test app::transition_context_tests::rejected_source_writeback_keeps_review_and_navigation_and_invalid_draft_still_blocks_start ... ok
|
||||
test app::transition_context_tests::scenario_transition_focuses_requested_counterpart_and_preserves_unrelated_views_in_both_directions ... ok
|
||||
test app::view_copy_tests::copying_architecture_keeps_architecture_even_with_a_retained_state_view ... ok
|
||||
test app::view_copy_tests::copying_the_current_state_view_uses_its_own_identity_and_is_one_source_undo ... ok
|
||||
test app::view_copy_tests::duplicate_rejection_preserves_an_incomplete_source_buffer ... ok
|
||||
test app::view_copy_tests::duplicate_rejection_preserves_invalid_property_and_pending_behavior_drafts ... ok
|
||||
test app::view_copy_tests::stale_copy_does_not_apply_an_unrelated_valid_property_draft ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_checkpoint_restores_inner_raw_draft_without_model_adoption ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_empty_actions_and_child_open_refuse_other_raw_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_app_modal_escape_then_child_back_then_parent_cancel_preserve_accepted_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_remains_available_after_owner_deletion_and_with_dirty_editors ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_back_retains_parent_and_rejects_late_child_event ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_default_consumer_name_has_stable_alias_and_correlated_selection ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_deleted_owner_view_retains_draft_instead_of_panicking_or_using_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_empty_history_reports_no_change_and_success_requires_a_real_history_step ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_existing_choice_prunes_staged_dependency ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_failed_source_budget_preserves_both_drafts_and_accepted_bytes ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_incomplete_recovered_kind_reports_error_without_panicking ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_inserts_work_on_the_exact_guarded_link_and_refuses_exchange_identity_conflict ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_lifelines_stage_exact_separate_records_and_one_history_entry ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_machine_before_any_owner_creates_optional_view_atomically ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_mounted_small_editor_keeps_back_and_use_outside_field_scroll ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_nested_semantic_parent_is_explicit_and_revalidated ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_new_callee_lifeline_preserves_caller_bindings_as_an_explicit_warning ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_old_empty_action_cannot_open_a_previous_owner_or_layer ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_owner_first_can_return_to_an_unnamed_machine_without_losing_source ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_recovery_keeps_inner_raw_fields_and_refuses_deleted_or_changed_owner ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_second_system_and_role_machine_owner_refuse_without_fallback ... ok
|
||||
test behavior::contextual_source_tests::contextual_source_work_uses_reserved_contribution_and_link_ids_and_one_undo ... ok
|
||||
test behavior::creation::app_tests::app_choosing_another_behavior_or_layer_cannot_commit_a_creation_draft ... ok
|
||||
test behavior::creation::app_tests::app_creation_opens_the_actual_new_owner_instead_of_first_or_previously_active_behavior ... ok
|
||||
test behavior::creation::app_tests::app_first_captured_escape_dismisses_file_or_pending_overlay_before_creation ... ok
|
||||
test behavior::creation::app_tests::app_lesson_request_cancel_retains_creation_then_escape_discards_only_the_draft ... ok
|
||||
test behavior::creation::app_tests::app_machine_behavior_submit_opens_its_opted_in_view_as_one_undoable_transaction ... ok
|
||||
test behavior::creation::app_tests::app_new_never_auto_applies_valid_or_invalid_property_and_source_drafts ... ok
|
||||
test behavior::creation::app_tests::app_recovered_rootless_sa_creation_retains_layer_ids_and_other_raw_drafts ... ok
|
||||
test behavior::creation::app_tests::app_stale_layer_open_never_starts_or_replaces_a_draft ... ok
|
||||
test behavior::creation::tests::all_four_viewpoints_are_explicit_and_survive_source_history_reopen ... ok
|
||||
test behavior::creation::tests::cancel_and_illegal_family_layer_switches_never_create_model_objects ... ok
|
||||
test behavior::creation::tests::corrupted_recovery_and_reserved_identity_collision_refuse_without_repairing_raw_values ... ok
|
||||
test behavior::creation::tests::creation_selection_rejects_changed_scenario_body_and_post_creation_operations ... ok
|
||||
test behavior::creation::tests::machine_requires_valid_owner_and_first_view_adds_no_region_or_state ... ok
|
||||
test behavior::creation::tests::mounted_creation_keeps_actions_visible_and_renders_only_six_owner_candidates ... ok
|
||||
test behavior::creation::tests::oa_process_and_sa_chain_keep_exact_names_root_ownership_and_one_history_entry ... ok
|
||||
test behavior::creation::tests::optional_context_collapses_without_losing_authored_reference_or_raw_search ... ok
|
||||
test behavior::creation::tests::owner_search_is_name_ordered_filtered_and_page_sized_not_a_catalog ... ok
|
||||
test behavior::creation::tests::post_commit_selection_is_correlated_with_exact_created_behavior_and_view ... ok
|
||||
test behavior::creation::tests::recovery_preserves_exact_raw_inputs_reserved_ids_and_revalidates_stale_owner ... ok
|
||||
test behavior::creation::tests::rejected_source_transaction_keeps_draft_and_every_accepted_source_byte ... ok
|
||||
test behavior::creation::tests::repeated_owner_names_remain_distinguishable_by_searchable_parent_context_and_alias ... ok
|
||||
test behavior::direct_canvas_tests::direct_alt_execution_stops_each_operand_at_its_reply_and_marks_open_operand ... ok
|
||||
test behavior::direct_canvas_tests::direct_bounds_change_during_held_drag_never_commits_old_slot ... ok
|
||||
test behavior::direct_canvas_tests::direct_clicked_occurrence_capture_cancels_on_view_and_context_changes ... ok
|
||||
test behavior::direct_canvas_tests::direct_context_escape_unfocus_and_pending_form_cancel_gestures ... ok
|
||||
test behavior::direct_canvas_tests::direct_drag_and_click_click_use_ordered_sources_and_publish_once ... ok
|
||||
test behavior::direct_canvas_tests::direct_execution_span_ends_at_its_correlated_reply_and_marks_an_open_call ... ok
|
||||
test behavior::direct_canvas_tests::direct_scroll_resize_and_bounds_changes_cancel_captured_slots ... ok
|
||||
test behavior::direct_canvas_tests::direct_scrolled_canvas_maps_raw_pointer_events_to_the_visible_slot ... ok
|
||||
test behavior::direct_canvas_tests::direct_selected_handle_reorders_and_hits_keep_semantic_identity ... ok
|
||||
test behavior::direct_canvas_tests::reused_exchange_messages_display_their_distinct_occurrence_names ... ok
|
||||
test behavior::scenario::data_contract_tests::large_payload_has_one_editor_with_reachable_field_and_authored_pages ... ok
|
||||
test behavior::scenario::data_contract_tests::recursive_browsing_up_and_root_keep_values_and_report_the_depth_limit ... ok
|
||||
test behavior::scenario::data_contract_tests::recursive_value_focus_exposes_authored_leaf_and_phase_changes_retain_surviving_keys ... ok
|
||||
test behavior::scenario::data_contract_tests::reply_call_picker_previews_the_same_value_reset_as_selecting_another_exchange ... ok
|
||||
test behavior::scenario::data_contract_tests::scenario_form_commits_two_reused_record_values_and_correlated_reply_atomically ... ok
|
||||
test behavior::scenario::direct_tests::direct_busy_save_keeps_observed_scroll_current_for_the_next_pointer_gesture ... ok
|
||||
test behavior::scenario::direct_tests::direct_clicked_occurrence_rejects_stale_slots_and_retains_recoverable_drafts ... ok
|
||||
test behavior::scenario::direct_tests::direct_clicked_occurrences_use_root_and_operand_slots_with_exact_source_history ... ok
|
||||
test behavior::scenario::direct_tests::direct_exchange_compatibility_browsing_preserves_final_slot_validation ... ok
|
||||
test behavior::scenario::direct_tests::direct_exchange_picker_is_bounded_and_browsing_keeps_pending_values ... ok
|
||||
test behavior::scenario::direct_tests::direct_five_hundred_exchange_choice_render_probe ... ok
|
||||
test behavior::scenario::direct_tests::direct_form_keeps_the_same_canvas_in_the_widget_tree ... ok
|
||||
test behavior::scenario::direct_tests::direct_middle_pair_insertion_is_one_exact_source_and_model_undo ... ok
|
||||
test behavior::scenario::direct_tests::direct_operand_pair_keeps_parent_sequence_and_cannot_reorder_across_operands ... ok
|
||||
test behavior::scenario::direct_tests::direct_reply_choices_cache_keeps_typing_fast_and_revalidates_changed_contexts ... ok
|
||||
test behavior::scenario::direct_tests::direct_reply_choices_validate_the_actual_slot_and_reorder_rejects_reverse_order ... ok
|
||||
test behavior::scenario::direct_tests::direct_scenario_reference_navigation_blocks_pending_drafts_and_stale_contexts ... ok
|
||||
test behavior::scenario::direct_tests::direct_scenario_reference_navigation_retains_each_exact_caller_without_history ... ok
|
||||
test behavior::scenario::direct_tests::direct_scenario_reference_return_survives_rename_and_rejects_deleted_or_changed_use ... ok
|
||||
test behavior::scenario::operation_tests::operation_gui_async_picker_uses_request_root_and_nested_directions_without_erasing_rejected_values ... ok
|
||||
test behavior::scenario::operation_tests::operation_gui_selects_two_parameterless_allocations_without_inventing_refinement_and_reply_derives_call ... ok
|
||||
test behavior::scenario::operation_tests::operation_gui_unresolved_and_disabled_selection_recovery_preserves_rejected_raw_values ... ok
|
||||
test behavior::scenario::tests::fragment_operands_accept_paired_messages_through_normal_destination_picker ... ok
|
||||
test behavior::scenario::tests::graphical_call_reply_is_atomic_correlated_and_source_equivalent ... ok
|
||||
test behavior::scenario::tests::invalid_lifecycle_edit_keeps_draft_and_timer_has_no_global_exchange ... ok
|
||||
test behavior::scenario::tests::lifeline_picker_uses_core_viewpoint_contract ... ok
|
||||
test behavior::scenario::tests::reverse_communication_canvas_choices_and_correlated_reply_share_core_direction ... ok
|
||||
test behavior::scenario::tests::scenario_reuse_requires_explicit_compatible_bindings ... ok
|
||||
test behavior::scenario::tests::tagged_scenario_commit_is_not_redirected_by_other_editor_events ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_allocates_remaining_height_and_pins_actions_at_minimum_and_wide_sizes ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_caller_restores_actual_mounted_canvas_and_shelf_with_camera ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_canvas_and_form_scroll_survive_disclosures_focus_width_and_resize ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_choosing_tools_preserves_valid_and_invalid_pending_editors ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_fit_reobserves_same_sized_owner_and_document_changes ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_fit_uses_measured_inner_viewport_and_rejects_nonfinite_inputs ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_open_and_back_restore_owner_and_mounted_scroll_after_preselection ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_scaled_and_scrolled_scene_keeps_clicked_slots_and_message_endpoints ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_scaled_nested_occurrences_and_reorder_keep_exact_sequence_identity ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_viewport_events_are_passive_guarded_and_do_not_apply_raw_forms ... ok
|
||||
test behavior::scenario::workspace::tests::scenario_workspace_whole_app_canvas_tree_survives_pending_shelves_and_focus ... ok
|
||||
test behavior::scenario_scroll::tests::direct_scenario_caller_restores_mounted_scroll_once_with_clamping_and_app_receipt ... ok
|
||||
test behavior::scenario_scroll::tests::direct_scenario_restore_cannot_scroll_another_document_owner_or_process_view ... ok
|
||||
test behavior::scenario_scroll::tests::direct_scroll_mounted_identity_resets_navigation_but_preserves_edits_before_first_report ... ok
|
||||
test behavior::scenario_scroll::tests::direct_scroll_observer_reports_actual_initial_clamped_and_remounted_offsets_once ... ok
|
||||
test behavior::scenario_scroll::tests::independent_process_owner_change_resets_actual_scroll_offsets ... ok
|
||||
test behavior::state_canvas::tests::context_menu_keeps_window_anchor_and_explicit_placement_identity ... ok
|
||||
test behavior::state_canvas::tests::context_tool_and_pending_form_changes_cancel_mutating_gestures ... ok
|
||||
test behavior::state_canvas::tests::creation_uses_the_explicit_deepest_owner_and_never_a_fallback_ancestor ... ok
|
||||
test behavior::state_canvas::tests::drag_uses_ordered_release_at_each_zoom_and_moves_descendants_in_one_undo ... ok
|
||||
test behavior::state_canvas::tests::escape_and_view_switch_discard_the_armed_transition_source ... ok
|
||||
test behavior::state_canvas::tests::internal_rows_and_pseudostate_hits_use_shared_persisted_geometry ... ok
|
||||
test behavior::state_canvas::tests::ordered_stationary_click_does_not_move_on_later_motion_in_the_same_batch ... ok
|
||||
test behavior::state_canvas::tests::pan_is_button_scoped_read_only_and_hover_does_not_reproject_the_scene ... ok
|
||||
test behavior::state_canvas::tests::pseudostate_names_avoid_rightward_and_downward_routes_and_share_hit_bounds ... ok
|
||||
test behavior::state_canvas::tests::relayout_does_not_turn_a_transition_click_into_a_drag_or_pan ... ok
|
||||
test behavior::state_canvas::tests::selected_endpoint_reconnect_preserves_identity_and_requires_handle_motion ... ok
|
||||
test behavior::state_canvas::tests::selection_relayout_does_not_move_nodes_or_change_drag_distance ... ok
|
||||
test behavior::state_canvas::tests::stacked_symbol_names_avoid_each_other_and_are_independent_of_input_order ... ok
|
||||
test behavior::state_canvas::tests::transition_supports_click_click_and_drag_without_coalesced_accidental_edges ... ok
|
||||
test behavior::state_canvas::tests::typed_state_actions_are_named_selectable_rows_before_internal_transitions_and_regions ... ok
|
||||
test behavior::state_canvas::tests::viewport_uses_full_canvas_coordinates_and_republishes_for_a_new_context ... ok
|
||||
test behavior::state_edit::tests::an_empty_machine_has_an_explicit_visible_owner_for_first_region_creation ... ok
|
||||
test behavior::state_edit::tests::connect_preserves_self_loops_and_rejects_hidden_or_incompatible_vertices ... ok
|
||||
test behavior::state_edit::tests::creation_places_missing_ancestry_and_unfolds_existing_owners_atomically ... ok
|
||||
test behavior::state_edit::tests::every_context_component_and_invalid_ownership_are_checked_before_planning ... ok
|
||||
test behavior::state_edit::tests::placing_existing_content_and_moving_a_folded_group_preserve_other_views_and_semantics ... ok
|
||||
test behavior::state_edit::tests::reconnect_preserves_the_complete_record_and_replaces_cardinality_in_place ... ok
|
||||
test behavior::state_edit::tests::view_initializes_only_its_machine_in_one_source_and_model_history_entry ... ok
|
||||
test behavior::states::tests::internal_choice_targets_self_and_edit_preserves_identity_and_description ... ok
|
||||
test behavior::states::tests::invalid_pseudo_trigger_keeps_draft_and_does_not_create_orphan_event ... ok
|
||||
test behavior::states::tests::selected_composite_owns_new_region_and_history_uses_selected_region ... ok
|
||||
test behavior::states::tests::timeout_and_work_trigger_commit_together_roundtrip_and_undo ... ok
|
||||
test behavior::tests::failed_document_commit_retains_typed_transition_and_time_event_for_repair ... ok
|
||||
test behavior::tests::legacy_process_and_chain_keep_their_ordered_exchange_scene ... ok
|
||||
test behavior::tests::one_behavior_form_survives_start_edit_and_unrelated_cancel_until_commit ... ok
|
||||
test behavior::tests::recovery_preserves_distinct_qualified_value_paths_and_rejects_invalid_payload_atomically ... ok
|
||||
test behavior::tests::recovery_retains_each_incomplete_behavior_form_without_executing_it ... ok
|
||||
test behavior::tests::selecting_state_transition_keeps_its_behavior_context ... ok
|
||||
test behavior::topology::contextual::tests::qualified_link_gui_deleted_transient_selection_does_not_seed_or_hide_retained_authored_endpoint ... ok
|
||||
test behavior::topology::contextual::tests::qualified_link_gui_nested_preview_folds_only_the_exact_reference_instance ... ok
|
||||
test behavior::topology::contextual::tests::qualified_link_gui_rejected_endpoint_keeps_exact_raw_intent_after_recovery ... ok
|
||||
test behavior::topology::contextual::tests::qualified_link_gui_repeated_sources_remain_distinct_and_apply_has_exact_source_history ... ok
|
||||
test behavior::topology::contextual::tests::qualified_link_gui_scope_paging_and_search_reach_tail_beyond_512_without_losing_endpoints ... ok
|
||||
test behavior::topology::contextual_routing::tests::contextual_route_native_x_to_first_b_keeps_visible_arrow_above_background_and_clear_of_other_references ... ok
|
||||
test behavior::topology::contextual_routing::tests::contextual_route_nested_visible_hidden_and_parallel_paths_keep_exact_addresses_and_legacy_routes ... ok
|
||||
test behavior::topology::contextual_routing::tests::contextual_route_shared_anchor_preserves_selected_direct_reconnect_at_fit_and_full_scale ... ok
|
||||
test behavior::topology::direct_tests::direct_process_append_preserves_existing_order_and_rejects_incompatible_exchange ... ok
|
||||
test behavior::topology::direct_tests::direct_process_controls_allow_incomplete_work_and_preserve_branch_semantics ... ok
|
||||
test behavior::topology::direct_tests::direct_process_empty_first_and_second_exchange_keep_the_same_interactive_renderer ... ok
|
||||
test behavior::topology::direct_tests::direct_process_imported_order_is_projected_without_mutation_and_first_canvas_edit_is_atomic ... ok
|
||||
test behavior::topology::direct_tests::direct_process_incompatible_imported_order_rejects_conversion_without_losing_draft ... ok
|
||||
test behavior::topology::direct_tests::direct_process_nested_source_reopen_and_api_command_use_one_transaction ... ok
|
||||
test behavior::topology::direct_tests::direct_process_oa_sa_repeated_occurrences_share_sources_and_split_one_guarded_link ... ok
|
||||
test behavior::topology::direct_tests::direct_process_palette_preserves_fit_and_manual_camera ... ok
|
||||
test behavior::topology::direct_tests::direct_process_pending_form_diff_retains_the_canvas_scroll_state ... ok
|
||||
test behavior::topology::direct_tests::direct_process_production_click_click_drag_insert_and_scroll_coordinates ... ok
|
||||
test behavior::topology::direct_tests::direct_process_production_endpoint_and_peer_reorder_handles_publish_exact_identity ... ok
|
||||
test behavior::topology::direct_tests::direct_process_production_stale_focus_scroll_bounds_and_pending_cancel ... ok
|
||||
test behavior::topology::direct_tests::direct_process_readable_default_fit_expansion_and_bounded_choices ... ok
|
||||
test behavior::topology::direct_tests::direct_process_real_picker_stays_bounded_and_search_keeps_selection ... ok
|
||||
test behavior::topology::direct_tests::direct_process_reconnect_delete_and_reorder_preserve_other_paths_and_sources ... ok
|
||||
test behavior::topology::direct_tests::direct_process_reuse_preview_is_local_expandable_and_recursive_sources_are_rejected ... ok
|
||||
test behavior::topology::direct_tests::direct_process_scaled_control_and_link_gestures_use_visible_positions ... ok
|
||||
test behavior::topology::direct_tests::direct_process_specific_parallel_link_and_incompatible_adjacency ... ok
|
||||
test behavior::topology::direct_tests::direct_process_three_ordered_exchanges_preserve_outer_paths_on_insertion ... ok
|
||||
test behavior::topology::tests::cycle_projection_terminates_and_retains_actual_links ... ok
|
||||
test behavior::topology::tests::empty_process_can_start_through_normal_authoring_events ... ok
|
||||
test behavior::topology::tests::fitting_a_branch_keeps_all_nodes_visible_and_selection_uses_scaled_coordinates ... ok
|
||||
test behavior::topology::tests::guarded_branch_is_one_transaction_with_distinct_source_identities ... ok
|
||||
test behavior::topology::tests::insertion_picker_only_offers_work_matching_adjacent_exchanges ... ok
|
||||
test behavior::topology::tests::legacy_branch_insertion_replaces_only_the_selected_implied_link ... ok
|
||||
test behavior::topology::tests::legacy_edit_preserves_order_and_new_work_in_one_undo ... ok
|
||||
test behavior::topology::tests::long_engineering_identifiers_stay_inside_label_width ... ok
|
||||
test behavior::topology::tests::process_fit_canvas_selection_ignores_retained_ordered_page_scroll ... ok
|
||||
test behavior::topology::tests::process_fit_disclosures_and_focus_preserve_rejected_raw_draft_and_accepted_source ... ok
|
||||
test behavior::topology::tests::process_fit_uses_measured_height_and_reports_minimum_without_changing_manual_zoom ... ok
|
||||
test behavior::topology::tests::reusable_preview_preserves_identity_and_filters_recursive_sources ... ok
|
||||
test behavior::topology::tests::stale_or_invalid_submit_preserves_inputs_and_creates_nothing ... ok
|
||||
test behavior::topology::tests::unlinked_contributions_do_not_gain_fictional_edges ... ok
|
||||
test behavior::topology::view::layout_tests::direct_process_pending_editor_uses_available_height_and_keeps_actions_visible ... ok
|
||||
test behavior::topology::view::layout_tests::process_fit_layout_disclosures_and_pending_editor_keep_real_manual_canvas_scroll ... ok
|
||||
test behavior::topology::view::layout_tests::process_fit_layout_measures_remaining_canvas_with_details_forms_and_window_resize ... ok
|
||||
test behavior::topology::view::layout_tests::process_fit_whole_app_focus_and_disclosures_retain_canvas_tree_with_pending_raw_form ... ok
|
||||
test connection_edit::tests::cancel_navigation_revision_and_dirty_drafts_cannot_commit_a_stale_connection ... ok
|
||||
test connection_edit::tests::visible_endpoint_drawing_commits_ports_and_exchange_once_with_exact_history ... ok
|
||||
test connection_tool::tests::boundary_candidates_match_core_orientation_and_reject_same_owner_or_mixed_kind ... ok
|
||||
test connection_tool::tests::boundary_feasibility_keeps_interface_warnings_and_final_carried_item_checks ... ok
|
||||
test connection_tool::tests::boundary_feasibility_rejects_dangling_identity_in_a_malformed_element_map ... ok
|
||||
test connection_tool::tests::direct_connections_share_exact_source_history_and_model_parity ... ok
|
||||
test connection_tool::tests::explicit_function_ports_keep_owners_contracts_and_do_not_invent_carried_items ... ok
|
||||
test connection_tool::tests::final_command_validation_rejects_invalid_models_without_mutation ... ok
|
||||
test connection_tool::tests::function_cards_use_unique_reuse_and_atomic_generation_when_ambiguous ... ok
|
||||
test connection_tool::tests::mismatched_port_owners_layers_and_contract_kinds_are_not_candidates ... ok
|
||||
test connection_tool::tests::operational_communication_uses_participants_without_creating_ports ... ok
|
||||
test connection_tool::tests::operational_interaction_targets_only_distinct_oa_activities ... ok
|
||||
test context_menu::tests::a_new_context_token_cannot_reuse_the_previous_mouse_press_or_scroll ... ok
|
||||
test context_menu::tests::actions_area_does_not_swallow_first_independent_click_after_overlay_consumed_its_release ... ok
|
||||
test context_menu::tests::anchors_outside_the_window_and_nonfinite_input_stay_bounded ... ok
|
||||
test context_menu::tests::clicking_disabled_or_dragging_off_an_action_never_executes_it ... ok
|
||||
test context_menu::tests::coalesced_dismissal_release_does_not_swallow_the_next_independent_click ... ok
|
||||
test context_menu::tests::empty_and_disabled_only_menus_still_capture_keys_and_escape_closes ... ok
|
||||
test context_menu::tests::keyboard_skips_headers_separators_and_disabled_actions_and_invokes_once ... ok
|
||||
test context_menu::tests::outside_dismissal_consumes_press_and_release_across_controlled_close ... ok
|
||||
test context_menu::tests::reconstructed_overlay_uses_retained_layout_for_rows_and_hit_testing ... ok
|
||||
test context_menu::tests::retained_overlay_layout_keeps_measured_width_and_scrollbar_after_reconstruction ... ok
|
||||
test context_menu::tests::tall_menu_clamps_to_viewport_and_keyboard_wheel_and_scrollbar_reach_the_end ... ok
|
||||
test data_values::tests::phase_choices_keep_reused_record_addresses_distinct ... ok
|
||||
test data_values::tests::recursive_picker_starts_with_distinct_leaf_names_and_sorts_them ... ok
|
||||
test data_values::tests::recursive_records_can_be_drilled_into_and_valid_imported_paths_resolve ... ok
|
||||
test data_values::tests::reference_parameter_stops_descent_and_unspecified_direction_remains_visible ... ok
|
||||
test data_values::tests::roots_and_one_hop_children_do_not_expand_unrelated_payload_branches ... ok
|
||||
test data_view::tests::allocation_rows_edit_relationship_identity_and_remove_only_that_allocation ... ok
|
||||
test data_view::tests::association_creation_is_a_separate_relation_with_editable_end_contracts ... ok
|
||||
test data_view::tests::browsing_pages_preserves_invalid_numeric_draft_and_inherited_allocation_identity ... ok
|
||||
test data_view::tests::contextual_data_actions_use_typed_defaults_and_one_undo ... ok
|
||||
test data_view::tests::large_inherited_dictionary_has_bounded_widgets_and_every_original_field_is_reachable ... ok
|
||||
test diagram::lifecycle_tests::menu_reset_and_draw_use_fresh_open_context ... ok
|
||||
test diagram::lifecycle_tests::middle_and_arrow_panning_preserve_source_and_history ... ok
|
||||
test diagram::lifecycle_tests::motion_after_release_must_not_move_clicked_port ... ok
|
||||
test diagram::lifecycle_tests::motion_after_source_click_release_must_not_create_connection ... ok
|
||||
test diagram::pointer_tests::coalesced_fe_ports_commit_once_through_app_and_source_history ... ok
|
||||
test diagram::pointer_tests::coalesced_port_drag_commits_once_through_app_and_source_history ... ok
|
||||
test diagram::pointer_tests::drag_from_already_selected_stationary_port_keeps_source_between_batches ... ok
|
||||
test diagram::pointer_tests::menu_captured_motion_must_not_turn_following_click_into_old_port_drag ... ok
|
||||
test diagram::pointer_tests::modal_and_stale_epoch_block_queued_connection_and_port_commits ... ok
|
||||
test diagram::port_hit_tests::coincident_ports_keep_selection_then_use_stable_identity ... ok
|
||||
test diagram::port_hit_tests::nearest_port_center_wins_on_all_borders_and_zoom_levels ... ok
|
||||
test diagram::port_hit_tests::nested_owner_palette_selection_drag_and_context_menu_pick_the_same_port ... ok
|
||||
test diagram::port_labels::tests::leaving_and_reentering_keeps_suppression_until_each_held_button_releases ... ok
|
||||
test diagram::port_labels::tests::menu_epoch_clears_suppression_when_the_overlay_consumes_release ... ok
|
||||
test diagram::port_labels::tests::outside_presses_do_not_suppress_and_cancel_or_focus_loss_clear_held_buttons ... ok
|
||||
test diagram::port_labels::tests::passive_layer_leaves_port_drag_selection_and_commit_with_the_interactive_canvas ... ok
|
||||
test diagram::tests::association_end_contracts_share_svg_geometry_and_select_without_moving_name_label ... ok
|
||||
test diagram::tests::bend_gestures_use_screen_hit_radius_and_commit_one_undo_at_three_zooms ... ok
|
||||
test diagram::tests::coincident_line_hit_retains_the_selected_connection ... ok
|
||||
test diagram::tests::connection_gestures_pick_real_ports_and_commit_coalesced_drag_at_every_zoom ... ok
|
||||
test diagram::tests::detached_label_selects_connection_and_occluding_card_owns_its_hit ... ok
|
||||
test diagram::tests::dragging_a_child_previews_the_same_enclosure_and_ports_as_commit ... ok
|
||||
test diagram::tests::fast_drags_commit_the_release_cursor_without_a_final_motion_event ... ok
|
||||
test diagram::tests::implicit_port_click_selects_semantics_and_drag_preview_svg_share_anchors ... ok
|
||||
test diagram::tests::route_cache_ignores_pan_zoom_and_cancelled_drag_cannot_commit ... ok
|
||||
test diagram::tests::routed_svg_has_same_polyline_label_and_bounds_as_canvas_scene ... ok
|
||||
test diagram::tests::svg_distinguishes_inferred_work_allocation_from_direct_allocation ... ok
|
||||
test diagram::tests::svg_preserves_visible_exchange_labels_and_capability_stereotypes ... ok
|
||||
test diagram::tests::typed_function_glyphs_and_unoriented_standard_connections_have_distinct_svg ... ok
|
||||
test diagram::view_options_tests::communication_svg_uses_saved_visibility_labels_and_direction ... ok
|
||||
test document::save_as_tests::save_as_preserves_explicit_source_entry_changes_in_history ... ok
|
||||
test document::save_as_tests::save_as_rebases_uniform_history_without_an_undo_step_or_lost_redo ... ok
|
||||
test document::save_as_tests::save_as_rejects_included_filename_collisions_in_past_and_future_without_mutation ... ok
|
||||
test document::save_as_tests::save_as_rejects_stale_or_content_changing_receipt_atomically ... ok
|
||||
test document::tests::accepted_history_keeps_the_latest_hundred_complete_snapshots ... ok
|
||||
test document::tests::altered_compiled_model_or_index_is_rejected_without_mutation ... ok
|
||||
test document::tests::asynchronous_save_marks_its_snapshot_without_cleaning_later_edits ... ok
|
||||
test document::tests::byte_budget_trims_oldest_history_without_discarding_a_large_current ... ok
|
||||
test document::tests::cached_view_index_tracks_accepted_creation_undo_and_redo ... ok
|
||||
test document::tests::comment_and_semantic_history_restore_exact_bytes_and_branch_together ... ok
|
||||
test document::tests::creation_selects_the_single_uuid_persisted_in_source ... ok
|
||||
test document::tests::invalid_project_is_rejected_before_format_can_normalize_it ... ok
|
||||
test document::tests::nested_cross_file_reparent_and_source_edit_share_exact_history ... ok
|
||||
test document::tests::no_op_command_or_source_apply_preserves_history_revision_and_redo ... ok
|
||||
test document::tests::omitted_id_stabilization_remains_dirty_until_exact_source_is_saved ... ok
|
||||
test document::tests::recreated_equal_record_does_not_inherit_deleted_source_ownership ... ok
|
||||
test document::tests::rejected_compile_command_and_writeback_preserve_state_and_redo ... ok
|
||||
test explorer::tests::collapse_and_search_retain_context_without_changing_collapse_state ... ok
|
||||
test explorer::tests::deep_containment_and_search_keep_the_full_path_without_recursion ... ok
|
||||
test explorer::tests::equal_names_have_stable_alias_and_identity_tie_breakers ... ok
|
||||
test explorer::tests::perspective_isolation_and_allocations_do_not_change_containment ... ok
|
||||
test explorer::tests::prefix_names_cannot_separate_a_parent_from_its_children ... ok
|
||||
test forms::data_fields::tests::defaults_distinguish_absent_empty_and_typed_literals_with_escaped_unicode ... ok
|
||||
test forms::data_fields::tests::field_browser_pages_every_direct_field_without_flattening_other_records ... ok
|
||||
test forms::data_fields::tests::independent_review_combined_take_type_informs_actual_default_form_in_both_directions ... ok
|
||||
test forms::data_fields::tests::numeric_bound_drafts_keep_partial_and_full_precision_values_out_of_accepted_state ... ok
|
||||
test forms::data_fields::tests::selecting_qualified_path_preserves_expression_typed_before_the_next_render ... ok
|
||||
test forms::data_fields::tests::semantic_reference_choices_follow_selected_mechanism_and_revert_on_keep ... ok
|
||||
test forms::data_fields::tests::supertype_picker_excludes_descendants_and_keeps_original_inherited_field_identity ... ok
|
||||
test forms::history_fields::tests::history_absent_baseline_and_empty_history_use_explicit_facts_and_exact_document_history ... ok
|
||||
test forms::history_fields::tests::history_clear_discards_inactive_invalid_constructors_before_reusing_the_same_row ... ok
|
||||
test forms::history_fields::tests::history_compound_value_and_constructor_variants_are_editable_without_live_context ... ok
|
||||
test forms::history_fields::tests::history_deleted_keys_and_observation_uuids_remain_exact_and_duplicate_history_rejects ... ok
|
||||
test forms::history_fields::tests::history_every_descriptor_fact_choice_matches_actual_closed_types_and_source_contract ... ok
|
||||
test forms::history_fields::tests::history_exact_strings_do_not_confuse_uuid_shaped_prose_or_literal_keys_with_references ... ok
|
||||
test forms::history_fields::tests::history_invalid_numbers_survive_constructor_switch_reorder_removal_and_recovery ... ok
|
||||
test forms::history_fields::tests::history_missing_semantic_field_can_be_added_and_removed_without_touching_prose_or_live_objects ... ok
|
||||
test forms::history_fields::tests::history_nested_optional_number_events_switch_absent_present_and_recover_invalid_raw ... ok
|
||||
test forms::history_fields::tests::history_nested_uuid_and_list_events_preserve_present_values_and_tagged_item_branches ... ok
|
||||
test forms::history_fields::tests::history_optional_uuid_and_text_seed_absence_without_inventing_observations ... ok
|
||||
test forms::history_fields::tests::history_primitive_type_choices_remain_visible_inside_the_tagged_union ... ok
|
||||
test forms::history_fields::tests::history_retained_text_constructors_follow_exact_mode_without_changing_the_observation ... ok
|
||||
test forms::port_fields::tests::all_demo_records_roundtrip_through_graphical_and_escaped_string_drafts ... ok
|
||||
test forms::port_fields::tests::boundary_choices_honor_draft_direction_same_kind_and_direct_interface_items ... ok
|
||||
test forms::port_fields::tests::contract_choices_follow_owner_and_never_offer_legacy_or_oa_typed_ports ... ok
|
||||
test forms::port_fields::tests::failed_shape_keeps_incomplete_text_and_saved_contract_payloads ... ok
|
||||
test forms::port_fields::tests::functional_endpoints_require_owner_direction_and_items_but_retain_bad_current_choice ... ok
|
||||
test forms::port_fields::tests::interface_roles_offer_participants_and_component_ports_independent_of_orientation ... ok
|
||||
test forms::port_fields::tests::port_allocation_choices_use_actual_owner_direction_and_ignore_edited_relation ... ok
|
||||
test forms::port_fields::tests::standard_switch_retains_incompatible_orientation_until_explicit_repair ... ok
|
||||
test forms::port_fields::tests::switching_function_direction_preserves_invalid_items_and_each_authored_payload ... ok
|
||||
test forms::tests::data_and_port_choices_are_typed_but_retain_invalid_current_values ... ok
|
||||
test forms::tests::editing_allocation_offers_other_performers_without_counting_itself_twice ... ok
|
||||
test forms::tests::moving_placement_and_changing_identity_is_one_lossless_undoable_edit ... ok
|
||||
test forms::tests::parent_choices_reject_cycles_without_removing_clear_or_current_choice ... ok
|
||||
test forms::tests::reply_and_reuse_forms_offer_semantically_compatible_references ... ok
|
||||
test forms::tests::scenario_choices_respect_owner_and_exchange_layer ... ok
|
||||
test forms::tests::semantic_port_group_choices_use_combined_owner_and_retain_invalid_transferred_items ... ok
|
||||
test forms::tests::shared_perspective_change_keeps_payload_and_rejects_incompatible_dependencies ... ok
|
||||
test forms::tests::state_observation_picker_keeps_work_lifelines_allocated_to_machine_owner ... ok
|
||||
test forms::tests::state_placement_form_uses_draft_destination_membership_without_changing_other_views ... ok
|
||||
test forms::tests::state_projection_form_keeps_string_variants_and_requires_a_typed_context ... ok
|
||||
test forms::view_fields::tests::category_family_change_retains_members_until_explicit_correction ... ok
|
||||
test forms::view_fields::tests::selective_view_property_apply_recovery_and_undo_preserve_semantics_and_empty_choices ... ok
|
||||
test guide::tests::filtering_and_related_navigation_keep_selection_visible ... ok
|
||||
test guide::tests::guide_topic_navigation_resets_only_article_and_same_topic_search_keeps_scroll ... ok
|
||||
test guide::tests::search_finds_concepts_in_walkthroughs_and_api_reference ... ok
|
||||
test home::tests::corrupt_future_and_oversized_history_are_preserved_with_usable_session_history ... ok
|
||||
test home::tests::failed_metadata_replace_keeps_previous_history_and_reports_memory_only_entry ... ok
|
||||
test home::tests::first_and_replaced_metadata_are_parseable_and_contain_no_model_bytes ... ok
|
||||
test home::tests::forgotten_and_missing_files_never_change_the_model_or_other_entries ... ok
|
||||
test home::tests::loading_missing_history_does_not_create_files_or_directories ... ok
|
||||
test home::tests::malformed_entries_and_unknown_fields_never_become_open_requests ... ok
|
||||
test home::tests::successful_local_history_is_bounded_ordered_deduplicated_and_durable ... ok
|
||||
test home::tests::unavailable_location_can_reappear_on_refresh_without_losing_identity ... ok
|
||||
test home::tests::walkthrough_uses_packaged_bundle_before_development_and_reports_missing_assets ... ok
|
||||
test hosted::client::tests::hosted_endpoint_validation_redacts_secrets_and_preserves_proxy_paths ... ok
|
||||
test hosted::client::tests::hosted_lost_publication_response_is_uncertain_without_retry ... ok
|
||||
test hosted::client::tests::hosted_open_rejects_incoherent_envelopes_missing_etags_and_unstable_ids ... ok
|
||||
test hosted::client::tests::hosted_oversized_local_bundle_is_rejected_before_network_admission ... ok
|
||||
test hosted::client::tests::hosted_production_auth_proxy_prefix_and_located_rejection ... ok
|
||||
test hosted::client::tests::hosted_production_roundtrip_preserves_comments_noops_and_conflicts ... ok
|
||||
test hosted::client::tests::hosted_publication_race_keeps_receipt_identity_for_review ... ok
|
||||
test hosted::client::tests::hosted_publication_retains_known_resource_after_failed_followup ... ok
|
||||
test hosted::client::tests::hosted_put_preserves_an_opaque_etag_and_compiles_the_accepted_bundle ... ok
|
||||
test hosted::client::tests::hosted_redirect_is_not_followed_or_retried_and_problem_tokens_are_redacted ... ok
|
||||
test hosted::client::tests::hosted_response_limits_cover_declared_and_chunked_bodies ... ok
|
||||
test hosted::client::tests::hosted_structured_mutation_failures_distinguish_precommit_rejections ... ok
|
||||
test hosted::client::tests::hosted_timeout_and_disconnect_leave_mutation_outcomes_explicit ... ok
|
||||
test model_menu::tests::add_bend_here_uses_context_point_and_one_source_aware_history_change ... ok
|
||||
test model_menu::tests::late_menu_actions_do_not_dismiss_new_menu_or_cross_view_context ... ok
|
||||
test model_menu::tests::menu_preserves_pending_properties_and_rejects_delayed_mutations ... ok
|
||||
test model_menu::tests::pending_source_allows_file_navigation_but_disables_model_actions ... ok
|
||||
test model_menu::tests::right_click_targets_actor_without_changing_selection_until_action ... ok
|
||||
test model_menu::tests::show_from_explorer_places_unfolds_and_keeps_semantic_selection ... ok
|
||||
test model_menu::tests::state_menu_folds_and_hides_only_its_captured_placement_and_rejects_stale_views ... ok
|
||||
test model_menu::tests::state_menu_keeps_typed_creation_reachable_and_preserves_pending_properties ... ok
|
||||
test navigation::tests::semantic_browser_finds_behavior_users_without_confusing_containment ... ok
|
||||
test port_edit::tests::all_border_drags_commit_exact_preview_and_restore_automatic_anchors_in_history ... ok
|
||||
test port_edit::tests::graphical_port_reparent_clears_old_anchors_in_the_same_history_operation ... ok
|
||||
test port_preview::tests::functional_creation_identifies_new_and_reused_endpoints_and_owners ... ok
|
||||
test port_preview::tests::legacy_split_discloses_endpoint_routing_item_origins_and_retained_evidence ... ok
|
||||
test port_preview::tests::reused_boundary_shows_item_union_and_existing_allocating_facts ... ok
|
||||
test port_preview::tests::synchronization_preview_exposes_contract_shrinkage_and_current_declaration_origin ... ok
|
||||
test port_workflow::recovery_tests::port_recovery_retains_authored_contract_and_identity_but_rebuilds_preview ... ok
|
||||
test port_workflow::tests::creating_typed_port_and_rejecting_stale_preview_preserve_drafts_and_identity ... ok
|
||||
test port_workflow::tests::graphical_function_exchange_and_component_generation_commit_and_undo_whole_contracts ... ok
|
||||
test port_workflow::tests::legacy_resolution_preserves_original_record_and_applies_as_one_undo ... ok
|
||||
test port_workflow::tests::port_creation_keeps_owner_diagram_and_unfolds_in_the_same_undo ... ok
|
||||
test port_workflow::tests::synchronization_uses_active_contract_instead_of_preserved_direction ... ok
|
||||
test recovery::source5::tests::source5_fingerprint_preserves_historical_field_order_and_diagram_shape ... ok
|
||||
test recovery::source5_tests::source4_checkpoint_remains_explicitly_unsupported_without_touching_disk ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_does_not_refresh_unrelated_clean_buffer_baseline ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_missing_identity_is_not_a_lossless_upgrade ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_old_diagram_property_shape_remains_editable ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_port_draft_replans_and_rejects_stale_base ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_preserves_dirty_invalid_text_and_baseline_exactly ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_preserves_distinct_unapplied_open_workspace ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_property_preserves_invalid_raw_input ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_upgrade_never_rewrites_checkpoint_or_origin ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_upgrades_only_header_and_clean_editor_baseline ... ok
|
||||
test recovery::source5_tests::source5_checkpoint_workflow_rebinds_only_the_proven_old_revision ... ok
|
||||
test recovery::source7_tests::source7_current_combined_contextual_and_operation_drafts_survive_without_execution ... ok
|
||||
test recovery::source7_tests::source7_explicit_new_fields_cannot_enter_frozen_old_model_profiles ... ok
|
||||
test recovery::source7_tests::source7_legacy_inactive_constructor_path_is_structural_but_raw_prose_is_not ... ok
|
||||
test recovery::source7_tests::source7_legacy_profile_workflow_and_semantic_drafts_replan_with_exact_base ... ok
|
||||
test recovery::source7_tests::source7_legacy_profiles_preserve_dirty_source_property_and_behavior_raw_fields ... ok
|
||||
test recovery::source7_tests::source7_legacy_structural_intent_rejects_even_null_but_never_scans_raw_strings ... ok
|
||||
test recovery::source7_tests::source7_legacy_view_selector_refuses_new_relation_kind_without_rewriting_checkpoint ... ok
|
||||
test recovery::source7_tests::source7_recovers_nonempty_frozen_5_and_6_profiles_with_exact_historical_binding ... ok
|
||||
test recovery::tests::altered_accepted_identity_and_unrecognized_raw_property_fields_reject ... ok
|
||||
test recovery::tests::exact_source_and_unfinished_invalid_buffers_restore_without_model_overwrite ... ok
|
||||
test recovery::tests::excess_retained_buffers_cannot_replace_the_last_recoverable_checkpoint ... ok
|
||||
test recovery::tests::invalid_open_retains_distinct_accepted_model_and_repair_workspace ... ok
|
||||
test recovery::tests::missing_includes_remain_reachable_repair_targets_without_fabricated_buffers ... ok
|
||||
test recovery::tests::multiple_sessions_replace_only_their_own_checkpoint_and_corruption_is_retained ... ok
|
||||
test recovery::tests::raw_invalid_property_number_survives_and_stays_rejected_until_repaired ... ok
|
||||
test semantic_review::artifacts_recovery_falsifier_tests::forged_artifact_draft_cannot_target_an_unreserved_or_non_artifact_identity ... ok
|
||||
test semantic_review::artifacts_recovery_falsifier_tests::forged_artifact_raw_variants_duplicate_addresses_and_unknown_fields_are_refused ... ok
|
||||
test semantic_review::artifacts_recovery_falsifier_tests::forged_artifact_reservations_cannot_duplicate_or_claim_an_existing_identity_or_another_owner ... ok
|
||||
test semantic_review::artifacts_recovery_falsifier_tests::legitimate_invalid_artifact_checkpoint_round_trips_and_prepares_only_after_explicit_repair ... ok
|
||||
test semantic_review::artifacts_tests::artifact_candidate_is_a_complete_record_not_a_tombstone_or_unattached_creation_shortcut ... ok
|
||||
test semantic_review::artifacts_tests::artifact_creation_and_identified_source_deletion_follow_core_metadata_and_history_boundary_both_directions ... ok
|
||||
test semantic_review::artifacts_tests::artifact_gui_reserves_recovers_and_creates_only_after_all_seven_metadata_reviews_both_directions ... ok
|
||||
test semantic_review::artifacts_tests::artifact_metadata_apply_and_exact_history_reset_are_one_source_preserving_undo_redo ... ok
|
||||
test semantic_review::artifacts_tests::artifact_move_metadata_none_empty_and_invalid_raw_recovery_are_independent_both_directions ... ok
|
||||
test semantic_review::artifacts_tests::artifact_moved_source_absence_deletes_but_destination_only_take_retains_both_directions ... ok
|
||||
test semantic_review::attachments::tests::absent_attachment_payloads_migrate_v1_and_v2_and_source5_upgrade_requires_exact_legacy_base ... ok
|
||||
test semantic_review::attachments::tests::addressed_attachment_candidates_equal_direct_core_oracle_both_directions ... ok
|
||||
test semantic_review::attachments::tests::attachment_apply_is_one_exact_source_and_history_undo_redo ... ok
|
||||
test semantic_review::attachments::tests::attachment_candidate_and_direct_record_keep_conflict_on_actual_slot_without_losing_drafts ... ok
|
||||
test semantic_review::attachments::tests::attachment_pair_drafts_survive_family_switch_and_restore_without_mutating_model ... ok
|
||||
test semantic_review::attachments::tests::functional_incident_source_requires_explicit_matching_port_review_in_one_atomic_candidate ... ok
|
||||
test semantic_review::attachments::tests::parent_and_each_endpoint_candidate_preserve_other_fields_and_match_core_both_directions ... ok
|
||||
test semantic_review::attachments::tests::raw_rejected_attachment_reference_survives_recovery_and_wrong_scope_is_rejected ... ok
|
||||
test semantic_review::attachments::tests::source_only_absence_and_explicit_absent_endpoint_are_different ... ok
|
||||
test semantic_review::attachments::tests::two_incident_endpoint_candidates_form_one_complete_record_and_recover_invalid_excluded_draft ... ok
|
||||
test semantic_review::batch_tests::batch_apply_is_one_exact_source_and_history_undo_redo_roundtrip ... ok
|
||||
test semantic_review::batch_tests::batch_candidate_conflict_keeps_both_raw_values_and_keep_is_a_real_constraint ... ok
|
||||
test semantic_review::batch_tests::batch_complete_constructor_cannot_erase_another_rows_new_literal ... ok
|
||||
test semantic_review::batch_tests::batch_constructor_retirement_conflicts_with_another_rows_kept_bound_in_both_orders ... ok
|
||||
test semantic_review::batch_tests::batch_delayed_text_targets_its_original_row_and_facet_without_switching_focus ... ok
|
||||
test semantic_review::batch_tests::batch_excluded_invalid_row_survives_focus_reopen_and_v2_recovery ... ok
|
||||
test semantic_review::batch_tests::batch_first_equal_constructor_acknowledgement_allows_an_independent_bound ... ok
|
||||
test semantic_review::batch_tests::batch_joint_bounds_use_one_candidate_and_match_an_independent_atomic_core_oracle ... ok
|
||||
test semantic_review::batch_tests::batch_reverse_distinct_targets_work_and_reverse_convergence_is_explicit ... ok
|
||||
test semantic_review::batch_tests::batch_v2_rejects_duplicate_included_sources_bad_addresses_and_stale_model ... ok
|
||||
test semantic_review::batch_tests::category_family_and_members_are_independent_core_checked_facets_both_directions ... ok
|
||||
test semantic_review::batch_tests::recovered_trace_picker_names_existing_trace_instead_of_deleted_reference ... ok
|
||||
test semantic_review::batch_tests::rejected_direction_switch_at_row_limit_preserves_every_recoverable_draft ... ok
|
||||
test semantic_review::compose::diagnostic_tests::distinct_review_conflict_keeps_trace_aliases_even_when_names_are_equal ... ok
|
||||
test semantic_review::compose::diagnostic_tests::reserved_creation_conflict_uses_its_rows_seed_instead_of_a_deleted_reference ... ok
|
||||
test semantic_review::compose::diagnostic_tests::same_review_presence_and_owner_conflict_names_both_facets_and_owners_and_retains_drafts ... ok
|
||||
test semantic_review::compose::diagnostic_tests::typed_owner_display_does_not_reinterpret_uuid_shaped_artifact_text ... ok
|
||||
test semantic_review::constructor_tests::closed_data_and_event_take_composition_matches_core_across_every_kind_pair_and_direction ... ok
|
||||
test semantic_review::constructor_tests::data_group_candidates_cover_every_definition_and_companion_default_both_directions ... ok
|
||||
test semantic_review::constructor_tests::data_group_retains_invalid_sibling_drafts_companion_default_and_variant_editor_buffers ... ok
|
||||
test semantic_review::constructor_tests::exchange_constructor_takes_qualified_annotation_addresses_without_remapping_expression_text ... ok
|
||||
test semantic_review::constructor_tests::existing_fragment_and_branch_group_candidates_edit_complete_owned_order_without_deletion ... ok
|
||||
test semantic_review::constructor_tests::group_take_reference_payload_and_scalar_candidate_match_core_and_one_document_batch ... ok
|
||||
test semantic_review::constructor_tests::historical_event_keep_retires_only_obsolete_branch_and_unchanged_kind_acknowledges_no_payload ... ok
|
||||
test semantic_review::constructor_tests::historical_same_kind_take_preserves_target_only_literals_when_composed_with_candidate ... ok
|
||||
test semantic_review::constructor_tests::occurrence_and_event_candidate_variants_cover_closed_families_without_touching_headers ... ok
|
||||
test semantic_review::constructor_tests::outer_and_nested_constructor_candidates_require_explicit_resolution_and_retain_both_drafts ... ok
|
||||
test semantic_review::constructor_tests::port_group_companions_typed_owner_context_and_direction_restrictions_are_explicit ... ok
|
||||
test semantic_review::constructor_tests::reverse_existing_typed_port_reviews_keep_or_candidate_legacy_without_permitting_typed_oa_write ... ok
|
||||
test semantic_review::constructor_tests::scenario_use_group_takes_typed_binding_references_and_preserves_source_text_both_directions ... ok
|
||||
test semantic_review::keyed_rows_tests::annotation_address_browser_descends_qualified_fields_without_changing_rows ... ok
|
||||
test semantic_review::keyed_rows_tests::annotation_observations_keep_uuid_shaped_expression_text_in_both_sides_and_history ... ok
|
||||
test semantic_review::keyed_rows_tests::batch_keyed_rows_compare_exact_target_slots_and_retain_independent_values ... ok
|
||||
test semantic_review::keyed_rows_tests::binding_choices_separate_reused_keys_from_local_lifelines ... ok
|
||||
test semantic_review::keyed_rows_tests::binding_local_picker_follows_a_candidate_parent_before_the_review_is_valid ... ok
|
||||
test semantic_review::keyed_rows_tests::binding_take_requires_local_correspondence_and_candidate_rejects_wrong_scenario ... ok
|
||||
test semantic_review::keyed_rows_tests::independent_rows_keep_take_candidate_match_core_and_preserve_siblings_both_directions ... ok
|
||||
test semantic_review::keyed_rows_tests::keyed_recovery_retains_raw_rows_and_staged_pairs_both_directions_without_applying ... ok
|
||||
test semantic_review::keyed_rows_tests::keyed_row_drafts_retain_expression_local_and_presence_across_decisions_and_staging ... ok
|
||||
test semantic_review::keyed_rows_tests::keyed_rows_distinguish_unpaired_source_from_explicit_absence_and_require_exact_reset ... ok
|
||||
test semantic_review::keyed_rows_tests::multiple_new_rows_compose_in_empty_collections_using_destination_key_order ... ok
|
||||
test semantic_review::keyed_rows_tests::row_review_apply_preserves_exact_source_and_semantic_history_through_undo_redo ... ok
|
||||
test semantic_review::keyed_tests::deleted_member_source_observation_removes_only_mapped_membership_both_directions ... ok
|
||||
test semantic_review::keyed_tests::exact_literal_new_rows_and_removals_commit_both_directions_without_default_loss ... ok
|
||||
test semantic_review::keyed_tests::exact_reset_only_is_one_history_source_transaction_and_undo_redo_both_directions ... ok
|
||||
test semantic_review::keyed_tests::function_port_members_use_existing_typed_choices_and_preserve_oa_legacy ... ok
|
||||
test semantic_review::keyed_tests::historical_one_sided_pair_migration_requires_exact_reset_and_explicit_overlap_resolution ... ok
|
||||
test semantic_review::keyed_tests::invalid_literal_removal_and_unselected_scalar_buffers_are_retained_and_repairable ... ok
|
||||
test semantic_review::keyed_tests::member_identity_labels_and_new_tabs_preserve_exact_names_and_deleted_keys ... ok
|
||||
test semantic_review::keyed_tests::reset_precedes_equal_constructor_candidate_and_preserves_independent_literal_draft ... ok
|
||||
test semantic_review::keyed_tests::staging_removal_and_obsolete_reset_recovery_keep_other_decisions_and_raw_presence ... ok
|
||||
test semantic_review::keyed_tests::stale_or_source_failed_reset_and_membership_apply_retain_exact_choices ... ok
|
||||
test semantic_review::keyed_tests::unordered_members_keep_take_candidate_preserve_other_rows_both_directions ... ok
|
||||
test semantic_review::keyed_tests::unsupported_independent_families_and_missing_identities_do_not_gain_edit_authority ... ok
|
||||
test semantic_review::message_kind_tests::message_group_candidate_closed_kinds_are_core_validated_in_both_directions ... ok
|
||||
test semantic_review::message_kind_tests::message_group_candidate_timer_switches_preserve_both_drafts_and_overlap_is_explicit ... ok
|
||||
test semantic_review::message_kind_tests::message_group_initial_equal_take_acknowledges_only_kind_and_checks_authored_timer_agreement ... ok
|
||||
test semantic_review::message_kind_tests::message_group_keep_historical_switch_retires_timer_and_completed_no_switch_rejects ... ok
|
||||
test semantic_review::message_kind_tests::message_group_rejects_protected_edits_stale_plan_and_source_failure_without_losing_timer ... ok
|
||||
test semantic_review::message_kind_tests::message_group_reply_and_reference_take_require_explicit_call_mapping_both_directions ... ok
|
||||
test semantic_review::message_kind_tests::message_group_take_full_timer_and_scalar_candidate_are_one_source_history_change_both_directions ... ok
|
||||
test semantic_review::message_kind_tests::message_group_timer_does_not_erase_exchange_without_its_own_selected_decision ... ok
|
||||
test semantic_review::ordered_tests::ambiguous_order_preserves_local_member_and_requires_explicit_candidate_positions ... ok
|
||||
test semantic_review::ordered_tests::historical_pair_restore_uses_exact_member_keys_and_never_zips_order_observations ... ok
|
||||
test semantic_review::ordered_tests::order_take_preserves_destination_only_positions_and_order_alone_cannot_add_members ... ok
|
||||
test semantic_review::ordered_tests::ordered_membership_choices_stage_exact_pairs_in_all_owner_shapes ... ok
|
||||
test semantic_review::ordered_tests::ordered_presence_keep_take_candidate_remove_only_selected_entry_and_order_take_reorders_only ... ok
|
||||
test semantic_review::ordered_tests::ordered_review_apply_is_exact_source_history_transaction_with_reopen_and_undo_redo ... ok
|
||||
test semantic_review::ordered_tests::ordered_take_uses_unique_anchors_and_matches_core_with_unrelated_candidate_both_directions ... ok
|
||||
test semantic_review::ordered_tests::raw_order_survives_membership_changes_decisions_and_recovery_until_explicit_reconcile ... ok
|
||||
test semantic_review::ordered_tests::several_incoming_members_follow_source_order_despite_independent_identity_sorting ... ok
|
||||
test semantic_review::recovery::tests::raw_scalar_and_closed_constructor_drafts_recover_against_exact_model_only ... ok
|
||||
test semantic_review::recovery::tests::version_one_without_orders_restores_raw_intent_and_replans_without_execution ... ok
|
||||
test semantic_review::source7_tests::contextual_incident_leaf_keep_allows_path_change_but_conflicts_with_changed_leaf_both_directions ... ok
|
||||
test semantic_review::source7_tests::reverse_operation_omission_gui_requires_raw_rationale_and_matches_one_core_batch_after_recovery ... ok
|
||||
test semantic_review::source7_tests::semantic_operation_virtual_none_candidate_uses_exact_allocation_and_preserves_accepted_bytes ... ok
|
||||
test semantic_review::tests::candidate_mixed_with_reference_take_uses_typed_correspondence_not_text_guessing ... ok
|
||||
test semantic_review::tests::deselected_invalid_candidate_is_retained_but_does_not_poison_another_selected_scalar ... ok
|
||||
test semantic_review::tests::explicit_trace_selection_updates_only_that_history ... ok
|
||||
test semantic_review::tests::first_equal_constructor_acknowledges_only_kind_and_allows_independent_leaves ... ok
|
||||
test semantic_review::tests::independent_review_clear_bound_ignores_retained_invalid_other_facet ... ok
|
||||
test semantic_review::tests::independent_review_keyed_fact_titles_keep_live_deleted_and_qualified_identity ... ok
|
||||
test semantic_review::tests::inherited_annotation_impact_requires_exact_acceptance_and_edits_clear_approval ... ok
|
||||
test semantic_review::tests::invalid_numeric_draft_and_protected_edits_retain_workflow_and_source ... ok
|
||||
test semantic_review::tests::read_only_structured_facts_and_partial_rollup_are_honest ... ok
|
||||
test semantic_review::tests::relation_candidates_preserve_endpoints_and_combine_selected_roles_and_bounds ... ok
|
||||
test semantic_review::tests::scalar_keep_take_candidate_commit_exact_source_and_history_in_both_directions ... ok
|
||||
test semantic_review::tests::scoped_literal_list_edits_preserve_unfinished_values_and_other_facet_buffers ... ok
|
||||
test semantic_review::tests::stale_plan_and_source_writeback_failure_do_not_lose_decisions_or_history ... ok
|
||||
test semantic_review::tests::state_kind_scalar_uses_typed_candidate_and_core_validation ... ok
|
||||
test semantic_review::view::reserved_artifact_tests::reserved_artifact_facet_and_reference_labels_survive_recovery_without_calling_it_deleted ... ok
|
||||
test source_navigation::tests::search_uses_utf8_columns_wraps_and_refreshes_after_edits ... ok
|
||||
test source_tree::tests::active_scroll_offset_uses_the_visible_order_and_retains_ancestor_context ... ok
|
||||
test source_tree::tests::collapsed_folders_retain_active_dirty_and_diagnostic_markers ... ok
|
||||
test source_tree::tests::deep_paths_build_expand_and_drop_on_a_small_stack ... ok
|
||||
test source_tree::tests::detached_buffers_keep_paths_and_only_clean_buffers_are_closable ... ok
|
||||
test source_tree::tests::exact_unicode_spaces_and_file_folder_name_collisions_are_not_normalized ... ok
|
||||
test source_tree::tests::folders_are_compact_and_sorted_before_files_without_losing_duplicate_basenames ... ok
|
||||
test source_workspace::tests::draft_history_budget_covers_inactive_files_without_discarding_drafts ... ok
|
||||
test source_workspace::tests::switching_retains_invalid_drafts_and_independent_history ... ok
|
||||
test tests::actor_port_creation_updates_containment_and_locate_reveals_its_owner ... ok
|
||||
test tests::adding_bend_between_close_ports_stays_outside_owner_clearance ... ok
|
||||
test tests::behavior_and_data_authoring_do_not_place_nodes_in_unrelated_architecture_views ... ok
|
||||
test tests::bidirectional_transition_ui_commits_once_and_preserves_other_diagrams ... ok
|
||||
test tests::counterpart_creation_focuses_visible_target_and_reuse_keeps_views ... ok
|
||||
test tests::creation_from_capabilities_routes_work_to_architecture_and_folded_allocation_inserts_below_existing_work ... ok
|
||||
test tests::dragging_keeps_semantic_selection_and_same_node_remains_editable ... ok
|
||||
test tests::escaped_string_mode_preserves_exact_control_characters ... ok
|
||||
test tests::every_demo_record_has_a_lossless_graphical_draft ... ok
|
||||
test tests::explicit_relationship_builder_never_mutates_on_preview ... ok
|
||||
test tests::explorer_and_creation_selection_follow_their_own_placement ... ok
|
||||
test tests::fit_adapts_to_canvas_returning_after_help_but_preserves_manual_navigation ... ok
|
||||
test tests::fit_uses_measured_canvas_bounds_and_preserves_them_on_open ... ok
|
||||
test tests::focused_explorer_follows_reparenting_without_changing_identity ... ok
|
||||
test tests::graphical_rename_keeps_aliases_and_references_and_undo ... ok
|
||||
test tests::identity_property_change_is_atomic_and_rewrites_all_live_references ... ok
|
||||
test tests::invalid_numeric_draft_survives_navigation_save_and_help ... ok
|
||||
test tests::invalid_save_and_continue_returns_to_repairable_draft ... ok
|
||||
test tests::malformed_source_preserves_model_and_is_recoverable ... ok
|
||||
test tests::manual_trace_requires_target_and_selection_normalizes_creation_kind ... ok
|
||||
test tests::mission_capability_authoring_is_contextual_atomic_and_text_equivalent ... ok
|
||||
test tests::modal_owns_background_commands_and_shortcuts ... ok
|
||||
test tests::nested_allocation_insertion_reflows_sibling_subtrees_and_preserves_fold_state ... ok
|
||||
test tests::opening_and_creating_models_preserve_the_actual_window_size_for_fit ... ok
|
||||
test tests::opening_legacy_source_surfaces_report_without_modifying_original_bytes ... ok
|
||||
test tests::pending_source_prevents_property_draft_collision_and_preserves_both_if_present ... ok
|
||||
test tests::placement_identity_edit_then_drag_and_diagram_identity_then_arrange ... ok
|
||||
test tests::placement_relocation_follows_cross_layer_traceability_view ... ok
|
||||
test tests::property_enum_and_optional_reference_roundtrip ... ok
|
||||
test tests::reopening_canvas_for_a_modal_preserves_viewport_after_route_edits ... ok
|
||||
test tests::revealing_an_implicit_function_port_unfolds_its_visible_architecture_owner ... ok
|
||||
test tests::routing_actions_are_atomic_guarded_and_fit_the_authored_detour ... ok
|
||||
test tests::selecting_current_constructors_preserves_payloads ... ok
|
||||
test tests::source_find_navigates_an_invalid_draft_without_applying_or_losing_it ... ok
|
||||
test tests::source_navigation_waits_for_editor_layout_and_cancels_on_edit ... ok
|
||||
test tests::system_only_models_open_the_populated_perspective ... ok
|
||||
test tests::transition_resolutions_belong_to_the_effective_target_and_kind ... ok
|
||||
test view_copy::tests::duplicate_retains_ports_routes_options_and_artifact_claims_with_exact_undo_redo ... ok
|
||||
test view_copy::tests::duplicate_state_view_preserves_machine_nesting_and_collapse_with_unique_aliases ... ok
|
||||
test view_copy::tests::missing_view_does_not_propose_an_empty_replacement ... ok
|
||||
test views::traceability::tests::traceability_browsing_retains_invalid_property_draft_and_existing_select_guard ... ok
|
||||
test views::traceability::tests::traceability_filter_reaches_artifacts_after_68_traces_and_searches_all_metadata ... ok
|
||||
test workflow::communication::tests::communication_requires_two_explicit_ports_and_recovers_the_partial_choice ... ok
|
||||
test workflow::port_authoring_tests::boundary_picker_matches_exact_commands_across_contracts_and_ownership ... ok
|
||||
test workflow::port_authoring_tests::boundary_picker_recomputes_for_unoriented_reverse_endpoints_without_relaxing_contracts ... ok
|
||||
test workflow::port_authoring_tests::duplicate_port_names_show_owner_contract_and_unique_alias ... ok
|
||||
test workflow::port_authoring_tests::fresh_functions_are_actual_picker_targets_and_plan_enables_apply ... ok
|
||||
test workflow::port_authoring_tests::generic_component_port_connection_keeps_its_endpoint_and_direction ... ok
|
||||
test workflow::port_authoring_tests::ordinary_standard_connections_default_unoriented_and_new_roles_exclude_legacy ... ok
|
||||
test workflow::recovery::tests::incomplete_relationship_and_trace_recover_raw_fields_and_reject_changed_model ... ok
|
||||
test workflow::recovery::tests::transition_recovery_replans_typed_request_without_persisted_commands ... ok
|
||||
test workflow::transition_tests::basic_transition_boundary_choice_is_required_without_an_inferred_system ... ok
|
||||
test workflow::transition_tests::basic_transition_creates_overview_when_existing_views_cannot_show_result ... ok
|
||||
test workflow::transition_tests::basic_transition_explicit_destination_appends_below_existing_bounds_and_is_one_source_edit ... ok
|
||||
test workflow::transition_tests::basic_transition_invalid_explicit_destination_retains_choice_and_refuses ... ok
|
||||
test workflow::transition_tests::basic_transition_reconcile_keeps_existing_selected_view_placement_and_route_exact ... ok
|
||||
test workflow::transition_tests::basic_transition_skips_lowest_uuid_state_view_and_preserves_oa ... ok
|
||||
|
||||
test result: ok. 675 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 448.33s
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"command": "arcadia-studio-tests.exe --test-threads=1",
|
||||
"started": "2026-09-11T12:01:47.3639508+00:00",
|
||||
"ended": "2026-09-11T12:09:15.9218331+00:00",
|
||||
"seconds": 448.5578823,
|
||||
"exit_code": 0,
|
||||
"executable_sha256": "6E677F58458B6122EA1886AAC98882640CD9CF260651FE3ECE62BDDA4BE38CC0"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"artifacts": [
|
||||
{
|
||||
"sha256": "6E677F58458B6122EA1886AAC98882640CD9CF260651FE3ECE62BDDA4BE38CC0",
|
||||
"file": "arcadia-studio-tests.exe",
|
||||
"bytes": 107061248
|
||||
},
|
||||
{
|
||||
"sha256": "F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4",
|
||||
"file": "libunwind.dll",
|
||||
"bytes": 190976
|
||||
}
|
||||
],
|
||||
"created": "2026-09-11T12:00:28.0285570Z",
|
||||
"testResult": "focused4:22 passed,0 failed,653 filtered; test inventory675",
|
||||
"sourceInputs": "../focused4-inputs.json"
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"created_utc": "2026-09-11T13:04:09.8807042Z",
|
||||
"scope": "37 byte-exact raw evidence records and 2 generated explanatory/readback files; inventory excludes itself",
|
||||
"raw_file_count": 37,
|
||||
"raw_bytes": 201835,
|
||||
"directory_file_count": 40,
|
||||
"files": [
|
||||
{
|
||||
"path": "desktop/clippy1-status.json",
|
||||
"source": ".local/contextual-source-20260911/clippy1-status.json",
|
||||
"bytes": 118,
|
||||
"sha256": "2D85A6E841E743B564B7AAFFA756F372739567F7728EE616B7122076218B77D6"
|
||||
},
|
||||
{
|
||||
"path": "desktop/clippy1.log",
|
||||
"source": ".local/contextual-source-20260911/clippy1.log",
|
||||
"bytes": 3126,
|
||||
"sha256": "75BB52CB0CAD69FF257F6C9F05D0514644975AA333BA2645BBEE41925FFFD432"
|
||||
},
|
||||
{
|
||||
"path": "desktop/clippy2-status.json",
|
||||
"source": ".local/contextual-source-20260911/clippy2-status.json",
|
||||
"bytes": 257,
|
||||
"sha256": "F876F56FA20383C206DBCA137E1A8999963C0A61A4B0547B22CEA67032E3827C"
|
||||
},
|
||||
{
|
||||
"path": "desktop/clippy2.log",
|
||||
"source": ".local/contextual-source-20260911/clippy2.log",
|
||||
"bytes": 157,
|
||||
"sha256": "DACDAADE0BFCF36EAC3550425B8D28AE0F266FE7AD57538F5B4D9C41FF8EEA87"
|
||||
},
|
||||
{
|
||||
"path": "desktop/fmt-final-status.json",
|
||||
"source": ".local/contextual-source-20260911/fmt-final-status.json",
|
||||
"bytes": 187,
|
||||
"sha256": "4FB53DC797C682977A180042219AA065B91C955081D0C1FA342D39CCFDE4FCA8"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused1-status.json",
|
||||
"source": ".local/contextual-source-20260911/focused1-status.json",
|
||||
"bytes": 118,
|
||||
"sha256": "114DBEAF0BF83EB2FDE30229D1CBEAAD9A877F804258719EACE9F71A5CDD9D5A"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused1.log",
|
||||
"source": ".local/contextual-source-20260911/focused1.log",
|
||||
"bytes": 4059,
|
||||
"sha256": "47D3071A768200CBF07972E602F64C586C428D444C49FD8C3757E05F33DADF2E"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused2-status.json",
|
||||
"source": ".local/contextual-source-20260911/focused2-status.json",
|
||||
"bytes": 118,
|
||||
"sha256": "751B73AABFB359352E70923DA243B33B2EF6EF11FBA7B3219C53372895776C40"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused2.log",
|
||||
"source": ".local/contextual-source-20260911/focused2.log",
|
||||
"bytes": 4738,
|
||||
"sha256": "5511947F161FBBA804DAF9F94A376A35D0FF7D0A137A98909C9872C25CC2BD7D"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused3-status.json",
|
||||
"source": ".local/contextual-source-20260911/focused3-status.json",
|
||||
"bytes": 118,
|
||||
"sha256": "71EAD5DBCA70CF34202BA02952A7291E4C0A9C65B14642FF8461377650251744"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused3.log",
|
||||
"source": ".local/contextual-source-20260911/focused3.log",
|
||||
"bytes": 3303,
|
||||
"sha256": "C7CF8FDBF4A5D2FAEA42053826D69791CE9235F9E6EE4350E74003DEB43F15A1"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused4-inputs.json",
|
||||
"source": ".local/contextual-source-20260911/focused4-inputs.json",
|
||||
"bytes": 44197,
|
||||
"sha256": "396255153B439B8427874E288E6C10D880A83CBDEDA345082B3F7D9A9722D629"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused4-status.json",
|
||||
"source": ".local/contextual-source-20260911/focused4-status.json",
|
||||
"bytes": 116,
|
||||
"sha256": "D1BBB26A1735523C2816003C98D6DB73841667886369B00DDB2639FAD5557FC4"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused4.log",
|
||||
"source": ".local/contextual-source-20260911/focused4.log",
|
||||
"bytes": 3211,
|
||||
"sha256": "3A286BC01FC19B9B48EF371E21659DFC215B7D7883D5FFD10DBC3406AAB4037A"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused5-delta.json",
|
||||
"source": ".local/contextual-source-20260911/focused5-delta.json",
|
||||
"bytes": 1681,
|
||||
"sha256": "14162287460DF568F2CB513146651691862DE4C16F57D165A9F047A9CA49C792"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused5-inputs.json",
|
||||
"source": ".local/contextual-source-20260911/focused5-inputs.json",
|
||||
"bytes": 44179,
|
||||
"sha256": "C0FB04418539D42186144BEC263F4A6D3B98BC51661B8460113E51292460A05B"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused5-status.json",
|
||||
"source": ".local/contextual-source-20260911/focused5-status.json",
|
||||
"bytes": 293,
|
||||
"sha256": "405169976AC379546E129E6D1FCA072B8F3660FE124B59CAE78584D61C3EC81A"
|
||||
},
|
||||
{
|
||||
"path": "desktop/focused5.log",
|
||||
"source": ".local/contextual-source-20260911/focused5.log",
|
||||
"bytes": 3341,
|
||||
"sha256": "80121F2815E2446891B6845140B5FCD106D78A37F543465177F5BDA4B8C8AE93"
|
||||
},
|
||||
{
|
||||
"path": "desktop/gui-final-status.json",
|
||||
"source": ".local/contextual-source-20260911/gui-final-status.json",
|
||||
"bytes": 232,
|
||||
"sha256": "976D790EAA2DD98CD86D56F1E8FDC571BD18DB6E1C06962E9BB4EA2F311BD935"
|
||||
},
|
||||
{
|
||||
"path": "desktop/gui-final.log",
|
||||
"source": ".local/contextual-source-20260911/gui-final.log",
|
||||
"bytes": 157,
|
||||
"sha256": "1D82FDE70BB41C4E2AF0DA35F970CCCBB91FC30247D28BC8D4AA6896EBE30DA5"
|
||||
},
|
||||
{
|
||||
"path": "desktop/gui-verified/manifest.json",
|
||||
"source": ".local/contextual-source-20260911/gui-verified/manifest.json",
|
||||
"bytes": 609,
|
||||
"sha256": "8B6F8938B66F5BB2E1BE805CB840F57765264B9C29B41845D94407037A561108"
|
||||
},
|
||||
{
|
||||
"path": "desktop/guide-final-status.json",
|
||||
"source": ".local/contextual-source-20260911/guide-final-status.json",
|
||||
"bytes": 281,
|
||||
"sha256": "A2F07DB7BD9FD5FCC28DE506A20EACCFFC9BE157CFB83258198443B19F21193C"
|
||||
},
|
||||
{
|
||||
"path": "desktop/guide-final.log",
|
||||
"source": ".local/contextual-source-20260911/guide-final.log",
|
||||
"bytes": 560,
|
||||
"sha256": "8A84A57A967097E16E320ED78818305487B5CED25159CD6DB2C54345C6D1788C"
|
||||
},
|
||||
{
|
||||
"path": "desktop/run-final-gates.ps1",
|
||||
"source": ".local/contextual-source-20260911/run-final-gates.ps1",
|
||||
"bytes": 1389,
|
||||
"sha256": "885C165B9937B6BDF8043AC945FF60C3CF31EAB7DB8323A0A16BD262F920124F"
|
||||
},
|
||||
{
|
||||
"path": "desktop/stage-final.ps1",
|
||||
"source": ".local/contextual-source-20260911/stage-final.ps1",
|
||||
"bytes": 2638,
|
||||
"sha256": "41D292C7066A265BB220BF3D67919BD531651931EEAC0301D7655A11DB668044"
|
||||
},
|
||||
{
|
||||
"path": "desktop/tests-final/manifest.json",
|
||||
"source": ".local/contextual-source-20260911/tests-final/manifest.json",
|
||||
"bytes": 623,
|
||||
"sha256": "0F143F45B4415C174E3D4879FB85A09851B10B2FFDC6B3F4435452C2A840EF84"
|
||||
},
|
||||
{
|
||||
"path": "desktop/tests-verified/full-desktop.log",
|
||||
"source": ".local/contextual-source-20260911/tests-verified/full-desktop.log",
|
||||
"bytes": 76384,
|
||||
"sha256": "DAD6B821863262F6420DF6D60D2225C529C79310E24F75D5DDA2C7892BF15D57"
|
||||
},
|
||||
{
|
||||
"path": "desktop/tests-verified/full-result.json",
|
||||
"source": ".local/contextual-source-20260911/tests-verified/full-result.json",
|
||||
"bytes": 302,
|
||||
"sha256": "737BC7053D7B63EC660C930EC578E6E21E3905BEE6D85A3BE9FDC9C49D97D561"
|
||||
},
|
||||
{
|
||||
"path": "desktop/tests-verified/manifest.json",
|
||||
"source": ".local/contextual-source-20260911/tests-verified/manifest.json",
|
||||
"bytes": 524,
|
||||
"sha256": "17AEA1E6AF2C86A77BBAE0AB41932CAE8CB82E8D197644B3C0BF2CF2A196B4C4"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/baseline-check.log",
|
||||
"source": ".local/staged-source-oracle-20260911/baseline-check.log",
|
||||
"bytes": 82,
|
||||
"sha256": "2D82DF14FB345414E164B57177D5A21C426F65C18EB5EF9E010984A92AD2E731"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/baseline-cli-check-result.json",
|
||||
"source": ".local/staged-source-oracle-20260911/baseline-cli-check-result.json",
|
||||
"bytes": 169,
|
||||
"sha256": "C9376E2458743B162E69EA67A16992D6F7D0D813636E82D8E616D0EB504A25E3"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/baseline-cli-check.json",
|
||||
"source": ".local/staged-source-oracle-20260911/baseline-cli-check.json",
|
||||
"bytes": 1902,
|
||||
"sha256": "66004F0718E5071F5F08C7DE11A4E8C503DF72EF018C799610111780D36A228F"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/build-initial-result.json",
|
||||
"source": ".local/staged-source-oracle-20260911/build-initial-result.json",
|
||||
"bytes": 94,
|
||||
"sha256": "14BF8DD87ADE8DFE2D230F350ADBC2BA9285B1488FB654AC4EB8C62C0C34F7C8"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/build-initial.log",
|
||||
"source": ".local/staged-source-oracle-20260911/build-initial.log",
|
||||
"bytes": 0,
|
||||
"sha256": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/checks-initial-result.json",
|
||||
"source": ".local/staged-source-oracle-20260911/checks-initial-result.json",
|
||||
"bytes": 100,
|
||||
"sha256": "28F505AF226299E2FF2660DF2BF73E84161D22AEA41229C6997F5B416738607B"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/manifest.json",
|
||||
"source": ".local/staged-source-oracle-20260911/manifest.json",
|
||||
"bytes": 1709,
|
||||
"sha256": "C76C7C6FF4EC1901662A0FCFB949761F6F112029D901D3BBE70E63068E83564A"
|
||||
},
|
||||
{
|
||||
"path": "oracle-preparation/self-check-initial.log",
|
||||
"source": ".local/staged-source-oracle-20260911/self-check-initial.log",
|
||||
"bytes": 763,
|
||||
"sha256": "6114C5BF9B75A27B4333E3DE38B3CAB08B976B2F01F3158AD8A7127FF7EE0ABB"
|
||||
},
|
||||
{
|
||||
"path": "README.md",
|
||||
"source": null,
|
||||
"bytes": 5833,
|
||||
"sha256": "AA559AFB8C75B6905E31F95D191BAE8688496FD1C0911330B9E2BCD043156CF6"
|
||||
},
|
||||
{
|
||||
"path": "source-freeze-readback.json",
|
||||
"source": null,
|
||||
"bytes": 3766,
|
||||
"sha256": "0CFA05BB91E52E6F0D4D9E11B5DBF84E0DD90DAA570D4422F3E4CCCDEA3C10E1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
PASS Baseline: complete Project + 2 exact source/disk files, original role UUIDs
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Command": "arcadia check harness/fixtures/staged-source-authoring/base/project.arcadia --json",
|
||||
"Exit": 0,
|
||||
"RecordedUtc": "2026-09-11T11:54:47.3267470Z"
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"entry": "harness/fixtures/staged-source-authoring/base/project.arcadia",
|
||||
"operation": "check",
|
||||
"status": "checked",
|
||||
"exit_code": 0,
|
||||
"written": false,
|
||||
"diagnostics": [
|
||||
{
|
||||
"severity": "warning",
|
||||
"code": "missing_system",
|
||||
"message": "Identify the SA system of interest.",
|
||||
"coordinate_space": "input",
|
||||
"location": {
|
||||
"path": "project.arcadia",
|
||||
"start": 11,
|
||||
"end": 121,
|
||||
"line": 2,
|
||||
"column": 1
|
||||
},
|
||||
"related": [],
|
||||
"object_id": "d1510000-0000-4000-8000-000000000001",
|
||||
"field": "elements"
|
||||
},
|
||||
{
|
||||
"severity": "warning",
|
||||
"code": "empty_sequence",
|
||||
"message": "Add ordered occurrences.",
|
||||
"coordinate_space": "input",
|
||||
"location": {
|
||||
"path": "project.arcadia",
|
||||
"start": 375,
|
||||
"end": 377,
|
||||
"line": 8,
|
||||
"column": 15
|
||||
},
|
||||
"related": [],
|
||||
"object_id": "d1510000-0000-4000-8000-000000000002",
|
||||
"field": "steps"
|
||||
},
|
||||
{
|
||||
"severity": "warning",
|
||||
"code": "empty_sequence",
|
||||
"message": "Add ordered occurrences.",
|
||||
"coordinate_space": "input",
|
||||
"location": {
|
||||
"path": "project.arcadia",
|
||||
"start": 581,
|
||||
"end": 583,
|
||||
"line": 13,
|
||||
"column": 15
|
||||
},
|
||||
"related": [],
|
||||
"object_id": "d1510000-0000-4000-8000-000000000003",
|
||||
"field": "steps"
|
||||
}
|
||||
],
|
||||
"changes": [],
|
||||
"identities_to_stabilize": 0,
|
||||
"migration": null,
|
||||
"notes": [
|
||||
"Diagnostic object IDs are omitted for declarations without authored IDs; lint's temporary identities are not the candidate's identities.",
|
||||
"Disk writes use the core journal/conflict checks. This is not cross-process atomic visibility or a power-loss durability guarantee; pending saves are never implicitly recovered. A failed write may require explicit journal recovery."
|
||||
]
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Exit": 0,
|
||||
"Seconds": 7.5659589,
|
||||
"FinishedUtc": "2026-09-11T12:01:48.0539296Z"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"SelfCheckExit": 0,
|
||||
"BaselineExit": 0,
|
||||
"FinishedUtc": "2026-09-11T12:02:24.4408700Z"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"RecordedUtc": "2026-09-11T12:03:07.0603355Z",
|
||||
"Build": {
|
||||
"Exit": 0,
|
||||
"Seconds": 7.5659589,
|
||||
"FinishedUtc": "2026-09-11T12:01:48.0539296Z"
|
||||
},
|
||||
"Checks": {
|
||||
"SelfCheckExit": 0,
|
||||
"BaselineExit": 0,
|
||||
"FinishedUtc": "2026-09-11T12:02:24.44087Z"
|
||||
},
|
||||
"Artifacts": [
|
||||
{
|
||||
"Path": "harness/staged-source-authoring-contract.rs",
|
||||
"Bytes": 22693,
|
||||
"SHA256": "9EB9DD3868B6CB772F907D16AE02995AD10A16F85C087012C24948E6E6FE775D"
|
||||
},
|
||||
{
|
||||
"Path": "harness/fixtures/staged-source-authoring/base/project.arcadia",
|
||||
"Bytes": 593,
|
||||
"SHA256": "AA844950EC4FB86F262A257E1FC370A26557EA7978D8A4CAB78265037660234C"
|
||||
},
|
||||
{
|
||||
"Path": "harness/fixtures/staged-source-authoring/base/notes.arcadia",
|
||||
"Bytes": 63,
|
||||
"SHA256": "AD9DE02963C20D1F43856455A797DEB05CA674659E45F2C4B96B52783024F8BD"
|
||||
},
|
||||
{
|
||||
"Path": ".local/target-gnullvm/debug/deps/liboa_core-3e81c616fea1d901.rlib",
|
||||
"Bytes": 99971382,
|
||||
"SHA256": "5018A1FD7286ED9DFEDCBBF5B68B399AD5D143F2A9AAAED3078CFC934C9589C4"
|
||||
},
|
||||
{
|
||||
"Path": ".local/staged-source-oracle-20260911/staged-source-authoring-contract.exe",
|
||||
"Bytes": 20864512,
|
||||
"SHA256": "967D9BA3C6FB3A7EFB410833903EC94556CA2D48A67D5072C8BB160F40A00F9C"
|
||||
},
|
||||
{
|
||||
"Path": ".local/staged-source-oracle-20260911/self-check-initial.log",
|
||||
"Bytes": 763,
|
||||
"SHA256": "6114C5BF9B75A27B4333E3DE38B3CAB08B976B2F01F3158AD8A7127FF7EE0ABB"
|
||||
},
|
||||
{
|
||||
"Path": ".local/staged-source-oracle-20260911/baseline-check.log",
|
||||
"Bytes": 82,
|
||||
"SHA256": "2D82DF14FB345414E164B57177D5A21C426F65C18EB5EF9E010984A92AD2E731"
|
||||
}
|
||||
]
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
PASS Lifeline: complete model/source fixed point, false-carrier metadata ignored, repeated-command refusal, one Undo/Redo, comment drift and explicit retained-file falsifiers; 3 reachable files
|
||||
PASS Chain: complete model/source fixed point, false-carrier metadata ignored, repeated-command refusal, one Undo/Redo, comment drift and explicit retained-file falsifiers; 4 reachable files
|
||||
PASS Machine: complete model/source fixed point, false-carrier metadata ignored, repeated-command refusal, one Undo/Redo, comment drift and explicit retained-file falsifiers; 6 reachable files
|
||||
PASS wrong source binding, machine owner and view geometry rejected; no native acceptance claimed
|
||||
PASS earlier-stage role identities remain pinned independently of a later carrier
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"checked_utc": "2026-09-11T13:02:51.2773935Z",
|
||||
"scope": "Read-only comparison of 13 desktop inputs with original focused5-inputs.json; no new build/test/native execution",
|
||||
"files": [
|
||||
{
|
||||
"path": "crates/oa-desktop/src/app.rs",
|
||||
"expected": "B10BFA57F331DA3928D5FE27D2AEBDB13F6054C6E3D48C4CFD24FF81726094AD",
|
||||
"actual": "B10BFA57F331DA3928D5FE27D2AEBDB13F6054C6E3D48C4CFD24FF81726094AD",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/app/checkpoints.rs",
|
||||
"expected": "55E5BABDCABEF767AF3BC8BE9CC3153B3F5CC0695701B890820EC0225643852E",
|
||||
"actual": "55E5BABDCABEF767AF3BC8BE9CC3153B3F5CC0695701B890820EC0225643852E",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior.rs",
|
||||
"expected": "C9E0AEA6A24CC982D0D82EE2B9B66F250CDFAC037B36BF6B1B9D7DD38246CD3C",
|
||||
"actual": "C9E0AEA6A24CC982D0D82EE2B9B66F250CDFAC037B36BF6B1B9D7DD38246CD3C",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/creation.rs",
|
||||
"expected": "CA7275B5C0118CBB78F5D16254E50FADDC26DBB53816D01950064C852E296B2E",
|
||||
"actual": "CA7275B5C0118CBB78F5D16254E50FADDC26DBB53816D01950064C852E296B2E",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/scenario.rs",
|
||||
"expected": "D12A4B1CAA61C08F69C4D2A64BD15568C4B7158DEA91AAC5A52A58A35ADB863C",
|
||||
"actual": "D12A4B1CAA61C08F69C4D2A64BD15568C4B7158DEA91AAC5A52A58A35ADB863C",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/scenario/workspace.rs",
|
||||
"expected": "69C7AD32E4BDC39F42D2E6C7764CFE1FA7867CD7DBCF9B904DEC805E6C912666",
|
||||
"actual": "69C7AD32E4BDC39F42D2E6C7764CFE1FA7867CD7DBCF9B904DEC805E6C912666",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/topology.rs",
|
||||
"expected": "D06B2F0FC39B4814E94200297E148F1D4D97E04CB167766030AC9DF18689E3B0",
|
||||
"actual": "D06B2F0FC39B4814E94200297E148F1D4D97E04CB167766030AC9DF18689E3B0",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/topology/contextual.rs",
|
||||
"expected": "EDC84FC69D8D4A8F4CE81A4452C4E2E35CFAF98ADDEED10235F392506C74E8B0",
|
||||
"actual": "EDC84FC69D8D4A8F4CE81A4452C4E2E35CFAF98ADDEED10235F392506C74E8B0",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/topology/direct.rs",
|
||||
"expected": "413AA2009EE4CBA0941836B43E41F16A04C8FC8568B6E92DB5BB08516E95C287",
|
||||
"actual": "413AA2009EE4CBA0941836B43E41F16A04C8FC8568B6E92DB5BB08516E95C287",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/topology/view.rs",
|
||||
"expected": "A7D806CD621BDF857C4E4861685CD3EB556B320DE3985B9CC3D9D131DAD370DC",
|
||||
"actual": "A7D806CD621BDF857C4E4861685CD3EB556B320DE3985B9CC3D9D131DAD370DC",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/guide.rs",
|
||||
"expected": "47EEB3CC0A48D5712720096015A08387CD354FB91559B0BD6FA106B5CAC6292C",
|
||||
"actual": "47EEB3CC0A48D5712720096015A08387CD354FB91559B0BD6FA106B5CAC6292C",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/source_draft.rs",
|
||||
"expected": "68F396C420FFF132FF0EAB82CB2C6251477412F6F9F90AD2E76C51A259F8A69A",
|
||||
"actual": "68F396C420FFF132FF0EAB82CB2C6251477412F6F9F90AD2E76C51A259F8A69A",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"path": "crates/oa-desktop/src/behavior/contextual_source_tests.rs",
|
||||
"expected": "5F05318A6533503B9D6FEBF1EC4DD7256F192394BC1B952A7904C8175BD8DDAE",
|
||||
"actual": "5F05318A6533503B9D6FEBF1EC4DD7256F192394BC1B952A7904C8175BD8DDAE",
|
||||
"unchanged": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
# Staged prerequisite source creation: frozen native contract
|
||||
|
||||
Codex-9e8r6t /root/palette_finish,2026-09-11. Prepared before inspecting any produced staged-source output. The standalone core-only evaluator is `harness/staged-source-authoring-contract.rs`. Root subsequently granted a direct-rustc window: warnings-denied compilation, self-check and exact baseline check **passed**. This validates the evaluator/fixture, not native staged-source creation. Existing immutable CLI admission of this starting fixture also succeeded with three ordinary completeness warnings. Build/provenance is in `harness/release-staged-source-authoring-oracle-20260911.md`.
|
||||
|
||||
Copy the whole `base` directory into a new isolated native work directory. Do not edit these source fixtures or overwrite an earlier checkpoint. Baseline has a root project, an empty explicit OA OperationalActivity scenario, an empty SA Functional chain and an independent Unicode comment include. All three persistent IDs are explicit; there are no existing activities/functions/participants, views, relations or traces.
|
||||
|
||||
| File | Bytes | SHA256 before native output |
|
||||
| --- | ---: | --- |
|
||||
| `base/project.arcadia` |593|`AA844950EC4FB86F262A257E1FC370A26557EA7978D8A4CAB78265037660234C`|
|
||||
| `base/notes.arcadia` |63|`AD9DE02963C20D1F43856455A797DEB05CA674659E45F2C4B96B52783024F8BD`|
|
||||
|
||||
## Exact cumulative native actions
|
||||
|
||||
1. OA Behavior → **Operational assessment**. The viewpoint is already **OperationalActivity**; use the semantic empty-state **Add first lifeline** action. Name the lifeline **Assessment lifeline**. Open **Create new source**, choose/retain Activity and layer-root semantic parent, and name it **Assess incident work**. Child **Use** returns to the retained parent. Verify the two distinct names, then apply the parent once. Only one root Activity plus one lifeline owned by the existing scenario, representing that Activity, should be created. Scenario steps remain empty; no occurrence, allocation, relation or view is implicit.
|
||||
2. SA Behavior → **System assessment**. Use **Add first function contribution**. Name the contribution **Classify this request**. Open **Create new source**, choose/retain Function and layer-root semantic parent, name it **Classify request**, and **Use**. Apply the retained parent once. Only one root Function and one Action occurrence under the existing chain should be created; the chain steps become exactly `[NEW_CONTRIBUTION]`. Its action is the new Function, lifeline is absent, conditions are empty. An isolated first contribution has no sequence link or allocation.
|
||||
3. SA Behavior → **New → State machine**. Name it **Field team operating modes**. Open **Create new owner**, explicitly select **SystemActor**, retain layer-root parent, name it **Field rescue team**, and **Use**. Check **Create the first state view**, then **Create and open** once. Only the root actor, its owned machine, and the opt-in diagram/root placement should be created. The diagram is **Field team operating modes · states**, SA StateMachine projection; default options, no routes/regions/states. Root placement is independently specified at60,60,size336×104 and passed through the shared core Layout command.
|
||||
|
||||
After each creation, Save and preserve a fresh whole-directory **first-commit** checkpoint. Undo **once**, Save and preserve another directory; Redo **once**, Save and preserve another. After all three, use the real file picker to reopen the final project, Save and preserve a final directory. If checking child Use before Apply or cancellation, save into a separate checkpoint and compare against the preceding accepted stage: no staged prerequisite may have been adopted.
|
||||
|
||||
All source/consumer names, ownership, references, defaults, membership and view geometry above are fixed expectations. The oracle borrows only unique fresh UUIDv4 roles by exact kind/layer/name (plus view projection and placement target). It never copies observed aliases, descriptions, parents, bodies, geometry, source text or diagrams wholesale. Every existing source byte and complete model field is compared after constructing the expected core-command result.
|
||||
|
||||
## Checker invocation and identity authority
|
||||
|
||||
After a root-authorized direct-rustc build using a matching completed `oa_core` rlib and `--edition2024 -D warnings`, let `$oracle` identify that immutable executable and `$base` the frozen baseline entry. Other variables below are preserved entry-file paths:
|
||||
|
||||
```powershell
|
||||
& $oracle self-check $base
|
||||
& $oracle check baseline $base $base
|
||||
& $oracle check lifeline $base $firstLifeline $firstLifeline
|
||||
& $oracle same $base $undoLifeline $firstLifeline
|
||||
& $oracle check lifeline $base $redoLifeline $firstLifeline
|
||||
& $oracle check chain $base $firstChain $firstLifeline $firstChain
|
||||
& $oracle same $firstLifeline $undoChain $firstChain
|
||||
& $oracle check chain $base $redoChain $firstLifeline $firstChain
|
||||
& $oracle check machine $base $firstMachine $firstLifeline $firstChain $firstMachine
|
||||
& $oracle same $firstChain $undoMachine $firstMachine
|
||||
& $oracle check machine $base $redoMachine $firstLifeline $firstChain $firstMachine
|
||||
& $oracle check machine $base $reopen $firstLifeline $firstChain $firstMachine
|
||||
& $oracle same $redoMachine $reopen
|
||||
```
|
||||
|
||||
Every stage supplies **all preceding original first-commit role carriers separately**. Those carriers are themselves checked against the cumulative contract. A later creation therefore cannot replace a prior stage's UUID and declare the replacement its own role authority; Redo and reopen cannot borrow new identities from their own output. The baseline source bytes are embedded in the checker at build time, so replacing the runtime fixture does not change its expected input.
|
||||
|
||||
The retained-file rule matches the corrected creation-v2 harness: normal checkpoints must have exactly reachable `.arcadia` files. `same EXPECTED ACTUAL UNDO_FROM` requires complete Project and reachable SourceBundle equality, and exact physical bytes equal to the explicitly proven first-commit disk map overlaid with EXPECTED's restored reachable files. Only those known detached files may remain. Unknown, changed or missing retained files fail. No file is taken from actual Undo output to define its own expected bytes. There is no broad orphan-file exemption.
|
||||
|
||||
Self-check prepares deliberately false metadata/geometry role carriers, full source fixed points, complete model/byte-drift falsifiers, exact repeated-command refusal, one core-session Undo/Redo, retained-file falsifiers and independent earlier-stage identity pinning. These **passed as evaluator checks**, not native acceptance. Predicted reachable-file counts are3 after Lifeline,4 after Chain and6 after Machine. Native focus, first-action discoverability, preserved raw parent/child drafts, selection, minimum/wide layout and real one-step history still require separate observation.
|
||||
@@ -0,0 +1 @@
|
||||
// Preserve this independent engineering note: secours 雨 Δ.
|
||||
@@ -0,0 +1,15 @@
|
||||
arcadia 7;
|
||||
project contextual_source_acceptance "Contextual source acceptance" id "d1510000-0000-4000-8000-000000000001" {
|
||||
include "notes.arcadia";
|
||||
|
||||
// The viewpoint is explicit before any lifeline exists.
|
||||
oa_scenario operational_assessment "Operational assessment" id "d1510000-0000-4000-8000-000000000002" {
|
||||
viewpoint OperationalActivity;
|
||||
steps [];
|
||||
}
|
||||
|
||||
// Contributions are occurrences; root Functions are separate sources.
|
||||
sa_functional_chain system_assessment "System assessment" id "d1510000-0000-4000-8000-000000000003" {
|
||||
steps [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
# Contextual prerequisite creation — implementation and evidence, 2026-09-11
|
||||
|
||||
Codex-9e8r6t /root/release_audit. Root-authorized bounded slice following `release-contextual-source-creation-plan-20260911.md`; independent review by `/root/behavior_audit`. Focused contract tests, strict lint, matching Windows GUI build and formatting passed. Root native/integration evidence remains separate as stated below. No native input, commits or release acceptance are claimed by this worker.
|
||||
|
||||
## Outcome and contract
|
||||
|
||||
An engineer can stage a missing semantic source inside a Scenario Lifeline, process/chain Work contribution, or new State machine owner form. Existing-source controls remain host-owned siblings; the external Codex-956atf reference chooser is untouched. Source and consumer names are independent. Participant kinds are explicit; OA Role is available for the appropriate lifeline only, never a machine owner. Semantic parent is shown explicitly, defaults visibly to the layer root where valid, and has a bounded searchable alternative list. MixedLegacy retains existing-source editing but no generic new-source catalog. Qualified Action creation and inferred allocations/capability involvement are excluded.
|
||||
|
||||
Option A from the frozen plan was chosen over suspending the form in Architecture (separate history/orphan risk) and multiplying dedicated source-plus-use tools (would not solve an already partially typed parent). Child Use validates/stages the prerequisite without adopting any model/source change. Back or Escape returns to the retained parent; final parent Apply/Create creates only its actively referenced staged dependency plus consumer and optional machine view in one validated transaction. Choosing an existing reference prunes the inactive source from that transaction.
|
||||
|
||||
`behavior/source_draft.rs` captures semantic document identity, typed reference scope, original owner, source name/kind/parent, child invocation token and reserved identities. Parent adapters retain their own raw fields, insertion/branch positions and invocation identity. Private preview Projects use existing core predicates; no staged object enters the accepted catalog. The parent planner's typed CreateElement/CreateRelation/reference/SetSteps records are remapped to reserved IDs, with aliases regenerated from those IDs. Machine/view IDs already reserved by the creation planner remain unchanged. Flattened final commands preserve exact command-correlated consumer selection after successful Document execution. Source write rejection retains both raw forms.
|
||||
|
||||
Scenario and process empty prompts count semantic children, not rendered/visible nodes. Scenario first actions carry the current canvas Context and recheck semantic emptiness; process reuses its Context-bound Begin at explicit append. Appearance/resize performs no mutation or focus operation. An unavailable pending owner is rendered as a retained-draft repair/cancel view before choosing any other owner.
|
||||
|
||||
## Independent criticism incorporated
|
||||
|
||||
- New Work adjacent to an Exchange must match its existing endpoint identity. A newly reserved source cannot do so; preserve the captured slot and refuse rather than retargeting the exchange or silently appending.
|
||||
- Source Use on an unnamed machine now stages its valid owner and returns, allowing the still-empty parent name to be completed without discarding the source.
|
||||
- Back is token-validated dismissal and remains available with stale/deleted owners or unrelated recovered raw editors; other source actions keep strict guards.
|
||||
- Recovered incomplete source kinds have a total summary, followed by a normal planning error rather than a panic.
|
||||
- Old empty-action events are scoped to their original canvas context. Missing-owner forms remain visible and do not fall through to another scenario/process and panic.
|
||||
|
||||
## Verification status
|
||||
|
||||
- `focused1.log` / `focused1-status.json`: compiler reported missing Clone for topology's private draft copy. The known-failed rustc was explicitly stopped; Cargo exit 101. No tests ran. Topology Draft/Browser/contextual Draft now derive Clone.
|
||||
- `focused2.log` / `focused2-status.json`: one guide `explain` call had an extra body argument. The known-failed compiler was stopped; Cargo exit 101, no tests ran. Corrected by merging the explanation body. The focused3 compiler then rejected a test calling a private App method; no tests ran. It was corrected to send the real Message::Command route. The successful focused4 gate includes the nested source-parent, unchanged caller-binding warning and no-op Undo/Redo status regressions.
|
||||
- `focused4.log` / `focused4-status.json`: PASS22/0,653 filtered out,2.04s execution after9m56s build. Test inventory675. Immutable `tests-verified/arcadia-studio-tests.exe` SHA256 `6E677F58458B6122EA1886AAC98882640CD9CF260651FE3ECE62BDDA4BE38CC0` (107061248bytes); sibling manifest and libunwind SHA256 `F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4`. Frozen source inputs: `focused4-inputs.json`. Root executed the immutable full suite: PASS 675/675 in 448.33s; `tests-verified/full-desktop.log` and `full-result.json`. This predates the narrow final origin, guide and lint corrections below.
|
||||
- Tests target exact source/consumer records, OA/SA strict viewpoints, source/consumer names and aliases, reserved-ID recovery/retry, one Undo/Redo and SourceBundle equality, inactive dependency pruning, second System refusal, Role owner refusal, guarded path insertion and exchange-adjacent refusal, raw source-budget failure, owner-first machine staging, modal Escape, dirty editor admission, recovered inner form, bounded footer geometry, stale CTA, malformed recovery and missing-owner rendering.
|
||||
- Source formatting and scoped whitespace check passed after the guide correction. Final post-review hardening also rechecks recovered typed source scope against the parent adapter; malformed-scope regression passed in focused4. The full675 snapshot passed as above; the matching final GUI/Clippy gates passed below; real native staged creation and minimum-window readability remain root gates. No Linux runtime or release packaging claim follows from this desktop slice.
|
||||
|
||||
Evidence directory: `.local/contextual-source-20260911/`. Frozen older native/creation/packaging artifacts remain unchanged.
|
||||
|
||||
|
||||
## Final origin and compatibility review
|
||||
|
||||
After child Back or switching to an existing source, a previously engaged parent must remain bound to its original semantic Project and exact consumer Element, even when no staged dependency reaches the command. Both Scenario and Work source-event admission and final command planning now compare that captured record against the actual parent draft owner. A valid different owner record cannot impersonate it. Missing-origin legacy recoveries bind only on their first valid, previously unengaged child Open; an already engaged recovery never silently rebinds. Back remains token-only dismissal. The worker found the post-Back/inactive command gap; independent reviewer confirmed it and sharpened the different-valid-owner recovery counterexample.
|
||||
|
||||
The additional 23rd focused test covers legacy/current recovery × Back/inactive-source for both Scenario and Work, with a valid unchanged control, exact raw preservation on different-Project rejection, missing-origin rejection and borrowed-valid-owner rejection in final preparation and child Open. This final addition passed in focused5: 23/23 contextual-source tests, 653 filtered out, 0.98s execution after 4m48s compilation. Final test inventory is 676. The same compiled test executable also passed guide-final 3/3 in 0.20s. Exact logs and status JSON are retained; strictClippy2 passed all targets with warnings denied in 4m29s; matching GUI and workspace formatting passed on the same frozen inputs.
|
||||
|
||||
`clippy1.log` / `clippy1-status.json` completed with exit101 on three `unnecessary_lazy_evaluations` in the empty Scenario first-action buttons. Those constant event values now use `then_some`. No other strict-lint diagnostic was emitted. The stale guide instruction to cancel and create a missing machine owner in Architecture was removed; sequence guidance now identifies work/exchange contributions accurately. These final changes are outside the full675 artifact.
|
||||
|
||||
|
||||
|
||||
## Owned source and integration boundary
|
||||
|
||||
All following source paths are under `crates/oa-desktop/src/`: `app.rs`, `app/checkpoints.rs`, `behavior.rs`, `behavior/creation.rs`, `behavior/scenario.rs`, `behavior/scenario/workspace.rs`, `behavior/topology.rs`, `behavior/topology/contextual.rs`, `behavior/topology/direct.rs`, `behavior/topology/view.rs`, `guide.rs`, and the new `behavior/source_draft.rs` / `behavior/contextual_source_tests.rs`. The contextual topology draft only gains Clone for private parent copies. Root owns integration/index/commits and native input; no core, server, schema/grammar or externally owned reference chooser changes belong to this implementation.
|
||||
|
||||
`focused5-inputs.json` records the frozen Rust/build-input scope and current commit context; `focused5-delta.json` records the seven changed desktop files relative to the passing full675 snapshot. It does not claim the uncommitted desktop source is contained in that commit. Immutable final test/GUI staging includes explicit manifests after all final gates and the unchanged-input check.
|
||||
|
||||
## Final frozen handoff
|
||||
|
||||
Final gate script completed exit0. `focused5.log` passed23/23 (0.98s), `guide-final.log` passed3/3 (0.20s), `clippy2.log` passed all targets with `-D warnings` (4m29s), `gui-final.log` passed the matching GUI build (6m20s), and `fmt-final.log` / status passed workspace formatting. Every gate has a separate started/finished/exitCode JSON. `stage-final.ps1` rechecked every recorded frozen input hash and refused existing output directories before copying. No source changed during these gates.
|
||||
|
||||
| Immutable artifact | SHA-256 | Bytes |
|
||||
| --- | --- | --- |
|
||||
| `gui-verified/arcadia-studio.exe` | `52DE82E434B636E18DB02D381842AA6DB84B721CFFD5502063F784F37246ACCE` | 112219136 |
|
||||
| `tests-final/arcadia-studio-tests.exe` | `405577A35CE643AC022885AF58706D6F8B321224AE6D68E2555FBFAF3D626F38` | 107101696 |
|
||||
| Both stages' `libunwind.dll` | `F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4` | 190976 |
|
||||
|
||||
Artifact paths are relative to `.local/contextual-source-20260911/`; each stage has `manifest.json`, linked to `focused5-inputs.json` and the explicit seven-file `focused5-delta.json`. The final executable contains676 tests; the full675 pass belongs to the preserved earlier artifact and is not relabeled as a full final676 execution. Only the affected23 and guide3 were run against the final test executable by this worker. Root can run any broader immutable gate without a Cargo build.
|
||||
|
||||
Root received the exact final GUI path/hash for independent staged-source native checks. `/root/palette_finish` received the released compiler lease for its separately authorized locked/offline CLI metadata. This worker performed no native GUI actions, release publication, Linux run, index staging or commits. The source/report ownership listed above is frozen; further source changes require an actual new finding and corresponding evidence scope.
|
||||
@@ -136,3 +136,257 @@ definitions. Those require further explicit semantic intent; they are not
|
||||
required to validate this staged-source slice. The external chooser remains
|
||||
owned separately. Implementation review and native evidence follow only after
|
||||
the author freezes the new source.
|
||||
|
||||
## Independent implementation review, 2026-09-11
|
||||
|
||||
Codex-9e8r6t `/root/behavior_audit`. Resumed after the author froze the first
|
||||
production candidate. Read issue #1 through #151 and traced the actual App,
|
||||
behavior dispatch, nested draft, recovery, view, and command-selection paths.
|
||||
The author made explicitly identified corrections between the first and second
|
||||
compile windows. This reviewer edited only this report and ran no Cargo, rustc,
|
||||
native input, or implementation tests. The author's first compilation exposed
|
||||
missing Clone derives; no passing runtime result is inferred from that compile.
|
||||
|
||||
Five independently derived counterexamples were sent directly to the author
|
||||
and root. All five have corresponding corrections in the second frozen source
|
||||
inspected here. The following is source verification, pending the author's
|
||||
19-case focused gate and root's native acceptance.
|
||||
|
||||
| Priority / finding in first candidate | Concrete counterexample and consequence | Correction inspected in second frozen source |
|
||||
| --- | --- | --- |
|
||||
| P1: missing pending owner can panic while rendering another owner | Recover source draft for scenario A after A is absent, with another same-layer scenario B present. `behavior::selected_owner` returns pending A, while `behavior::view` falls back to B. B's workspace calls `scenario_context().expect(...)`, but the context still resolves absent A and is None. Process fallback has the same mismatch. With no other owner, the pending form is hidden behind New instead. Safe `sources()` and `prepare_pending()` do not protect this render path. | `behavior::view` now checks the pending owner's presence/kind/layer before choosing a fallback. It shows the retained consumer name plus current child form or explicit parent Cancel. The child Back remains reachable; it never silently opens B as the pending consumer. New orphan-view tests construct both no-choice and remaining-B cases. |
|
||||
| P1: staged recovery completeness was assumed by presentation | Recover selected staged source with `source.staged.kind = null`, a valid value for its serialized `Option<Kind>`. Deserialization accepts it; `State::label` then calls `unwrap()` and panics in parent view/selection before command validation can return its existing missing-kind error. | `source_draft::State::label` is now total and displays a missing-kind label. Planning still refuses; raw recovery remains intact. A malformed-kind regression exercises both planning and the label. |
|
||||
| P2: owner-first machine creation cannot leave its valid child | New → Machine, leave machine name blank, Create new owner, choose valid kind/name, Use. The source is valid, but the parent handler calls `next.command(p)` and refuses the blank machine name. Parent edits are locked while the child is open; Back drops the entered owner before the machine can be named. | Machine Use stages the valid prerequisite and checks the actual eligible-owner predicate on its private preview. It does not require an already complete machine. Final Submit still validates the complete batch. The owner-first regression keeps the same source/name while the machine is subsequently named. |
|
||||
| P2: footer Back disagrees with Escape on retained stale/dirty recovery | After recovering unrelated dirty source/property text, App rejects every source event, including Back. After deleting/changing the owner, scenario/topology validate the origin before dispatching Back; the helper also compares scope first. The visible Back button refuses although global Escape succeeds through `source_back()`. | Token-only `source.dismiss` runs before semantic context checks. App exempts only `Source(Edit::Back)` from other-editor admission. Wrong/old tokens still refuse; Open and Use keep their guards. Added dirty-editor and deleted-owner Back regressions preserve parent/property state. |
|
||||
| P2: new empty actions accept a previous owner's event | Capture A's new first-action message, navigate to clean B or another layer, then deliver A's bare `Start(owner, tool)`. That route checks dirtiness and owner existence but carries no context. It can open A; `selected_owner` prioritizes the resulting pending owner. | Scenario CTAs now use `CanvasEvent::First(Context, Tool)` through the existing context and dirty guards, with a fresh semantic emptiness check. Process first Work uses its existing context-bound Begin with the explicit default insertion. A new owner/layer-stale CTA regression rejects old context and admits the current one. |
|
||||
|
||||
The source changes address the reported mechanisms. Their tests are authored
|
||||
regressions, not independently executed evidence in this review. In particular,
|
||||
constructing an orphan view prevents the identified `expect` panic but does not
|
||||
by itself prove its footer can be clicked at the minimum native window size.
|
||||
|
||||
The unchanged core contracts are used correctly in the inspected paths:
|
||||
|
||||
- App form start/source admission checks raw source and property dirtiness
|
||||
without calling generic Apply. Source/parent submission retains the existing
|
||||
dirty guard. Model-menu and modal Escape precedence is resolved before child
|
||||
Back, then parent cancellation. Raw edits and form rendering create no
|
||||
accepted model/history operation.
|
||||
- Source commands keep source name, semantic parent, kind, layer, document, and
|
||||
exact captured consumer/parent identity distinct from the consumer. Existing
|
||||
validation admits Role only where appropriate, enforces System uniqueness,
|
||||
and preserves allowed completeness warnings. No allocation, role realization,
|
||||
reuse binding, or shared exchange retargeting is inferred.
|
||||
- For an actively selected staged source, the helper previews the source,
|
||||
prepares the original consumer, remaps every new element/relation identity
|
||||
and typed reference plus SetSteps to the reserved set, then forms one flat
|
||||
validated batch. Recomputed aliases use the reserved IDs rather than an
|
||||
abandoned temporary UUID. Machine/view/placement identities remain reserved
|
||||
by the existing creation planner. This review does not claim that the older
|
||||
non-staged planners reserve their IDs across separate preparations.
|
||||
- App compares the complete prepared staged command before assigning its
|
||||
consumer selection, and assigns it only after `Document::execute` succeeds.
|
||||
Parent acknowledgement follows success. Choosing an existing reference makes
|
||||
the staged source inactive: preview/combine omit it, so it is not published.
|
||||
Parent Cancel drops the entire pending state.
|
||||
- Captured process link identity/endpoints and presentation-before slot remain
|
||||
validated. Work insertion preserves the existing guarded link and adds the
|
||||
new successor link; a fresh source next to an existing Exchange still cannot
|
||||
impersonate the required endpoint and refuses with raw input retained.
|
||||
- New empty guidance counts semantic Lifeline/Occurrence/contribution records,
|
||||
rather than rendered positions. An unresolved lifeline is still a lifeline;
|
||||
ScenarioUse, fragment, and offscreen content do not become empty merely
|
||||
because of presentation. Existing scenario canvas/scroll slots remain in the
|
||||
surrounding workspace tree while the explicit child form occupies its form
|
||||
pane.
|
||||
|
||||
The author deliberately made explicit staged-consumer names exact, including
|
||||
leading/trailing whitespace; source names are also exact, and a blank consumer
|
||||
continues to default to its chosen source name. This supersedes the earlier
|
||||
matrix's inherited trimming expectation **for active staged-source consumers**.
|
||||
The older existing-reference consumer path still has its pre-existing trim
|
||||
policy. Native/oracle expectations must distinguish those paths and must not
|
||||
borrow an observed output name to define the expected model.
|
||||
|
||||
Second frozen source fingerprints captured at approximately 11:39 UTC:
|
||||
|
||||
| File | SHA-256 |
|
||||
| --- | --- |
|
||||
| `crates/oa-desktop/src/app.rs` | `81E0AA21A93126D716E628B3EBD440201AB19D6B578E2585F5E500072244D58B` |
|
||||
| `crates/oa-desktop/src/behavior.rs` | `A0E595F17F254002F1FBD7984EEB679320DAB042CA310C38D8916F0055713780` |
|
||||
| `crates/oa-desktop/src/behavior/source_draft.rs` | `32057E30C0526FA674D463F47C4EAC7C0F391B1F4C5060757981A3CBED16C6AE` |
|
||||
| `crates/oa-desktop/src/behavior/scenario.rs` | `759805631BE9E8526DACFB959D91C76CA1A2A40F47F8645BCEB0E0C15B77E326` |
|
||||
| `crates/oa-desktop/src/behavior/topology.rs` | `8E1C65AFE4C7C097F683B33A6DF237219F48AFD1E81F81329B07612F4D6994CC` |
|
||||
| `crates/oa-desktop/src/behavior/creation.rs` | `BE75840293E84FCAE90DC6D17CCD6630A586B389FB189ADF73D1E9B046CE3DE2` |
|
||||
| `crates/oa-desktop/src/behavior/contextual_source_tests.rs` | `242B68E0DFF14E57E1F510EA3DEA95ED1B2ADCDABFD24C9F493FC871CB50F049` |
|
||||
|
||||
No additional implementation blocker was found in this bounded review. Required
|
||||
evidence still includes terminal focused checks and native minimum/wide form
|
||||
authoring, plus independent complete model/source comparison for actual
|
||||
source/consumer creation and Undo/Redo/reopen. The earlier explicit detached-file
|
||||
retention rule remains unchanged. No native result, full-suite result, or release
|
||||
completion is claimed here.
|
||||
|
||||
## Final staged-source delta review, 2026-09-11
|
||||
|
||||
Codex-9e8r6t `/root/behavior_audit`. Reviewed only the changes after the recorded
|
||||
second freeze: compact consumer captions, explicit creation summaries, recovered
|
||||
typed-scope validation, nested semantic-parent and callee/caller regressions,
|
||||
guide correction, and App Undo/Redo result handling. Read the final author gate
|
||||
and current Gitea decisions through #178. No production edits, Cargo, rustc or
|
||||
native input; root retains the immutable full-suite run and native acceptance.
|
||||
|
||||
The source inspected in this pass matched all ten corresponding entries in
|
||||
`.local/contextual-source-20260911/focused4-inputs.json`: App, behavior, source
|
||||
draft, scenario, scenario workspace, topology, topology view, creation,
|
||||
contextual-source tests and guide. This identifies the precise compiled source
|
||||
without presenting the earlier second-freeze fingerprints as current.
|
||||
|
||||
### Concrete corrections identified at the final boundary
|
||||
|
||||
1. **P2 — The State machine guide still directs the user out of the new flow.**
|
||||
At `guide.rs:547`, the first step says to cancel and create a missing owner in
|
||||
Architecture; the immediately following new step describes Create new owner
|
||||
with the retained machine draft. The old sentence would unnecessarily lose
|
||||
the user's pending setup and hides the new supported route. Sent directly to
|
||||
the author/root; the author removed it after the Clippy source freeze and
|
||||
this reviewer confirmed the source readback. The guide's previously rejected
|
||||
`explain` argument count is already corrected in the passing focused4 source.
|
||||
|
||||
2. **P2 — The source origin must survive inactive dependency planning.**
|
||||
The author identified this additional case before review closure, and this
|
||||
reviewer independently confirmed its actual code path. Start a Lifeline or
|
||||
Work form with a valid existing target, open Create new source, then Back.
|
||||
`source.engaged` remains true, but there is no editing/active staged source.
|
||||
`check_scope` and `preview` therefore pass without a source-side document
|
||||
check. Parent `Draft::command` at scenario.rs:1350/topology.rs:582 then reaches
|
||||
its ordinary consumer planner against a different `Project.id` with the same
|
||||
owner and target UUIDs. The captured `source_origin` is checked only while
|
||||
handling Source events. Use followed by reselecting an existing source has
|
||||
the same inactive-dependency mechanism. This is a concrete preparation-boundary
|
||||
failure; no claim is made that ordinary file navigation preserves the form
|
||||
through its existing App reset.
|
||||
|
||||
The narrow proposed correction checks captured document plus exact owner at
|
||||
final command preparation whenever source creation has been engaged, keeping
|
||||
token-only Back and cancellation available. Regression must begin with a
|
||||
valid existing target, prove baseline preparation succeeds, then refuse the
|
||||
other document while retaining all raw fields. A compatibility edge was sent
|
||||
separately: old recovered forms legitimately have `source_origin=None` and
|
||||
unengaged default source state. Their first successful source Open should bind
|
||||
the current origin; an already engaged missing/mismatched origin must never
|
||||
be silently rebound. The author implemented these document/legacy controls
|
||||
after the source freeze, with a valid-target Scenario/Work × Back/inactive ×
|
||||
ordinary/legacy regression matrix. That later source is not covered by
|
||||
focused4 and no new execution is claimed here.
|
||||
|
||||
**One final owner-binding detail remains at this handoff.** The initial new
|
||||
guard compares the captured owner with `p.elements.get(&owner.id)`. A recovered
|
||||
origin can contain another valid, unchanged same-layer owner B while the
|
||||
parent draft still targets A. That lookup validates B against itself; the
|
||||
otherwise valid consumer planner still operates on A. Compare the captured
|
||||
owner record with `p.elements.get(&self.owner)` in final planning and
|
||||
`p.elements.get(&d.owner)` in Source-event admission, or explicitly require
|
||||
the two IDs to agree. The simplest negative control replaces only the
|
||||
serialized origin's owner record with B, leaving the valid target/slot and
|
||||
actual draft owner A unchanged. This avoids a false rejection caused by an
|
||||
unrelated invalid Scenario parent slot. This reviewer sent that independently
|
||||
derived detail to author/root; final strengthened source readback is pending.
|
||||
|
||||
### Confirmed scope of the other deltas
|
||||
|
||||
- New outer consumer captions call `views::short` with 60 characters, or 80 in
|
||||
the orphan card. That helper collapses whitespace and truncates presentation;
|
||||
it does not rewrite raw draft names. The source fields still have their own
|
||||
remaining-height scroller and a separate Back/Use footer. Active-source
|
||||
summaries describe the actual source+lifeline/work/machine transaction, with
|
||||
the first machine view explicitly conditional. No view call adopts a model
|
||||
command. Native minimum-window readability is not inferred from this trace.
|
||||
- `source.check_scope` is called before preview in all three parent planners.
|
||||
A selected staged source or current child with the wrong typed consumer scope
|
||||
is rejected; an inactive staged source remains excluded. The malformed-kind
|
||||
regression now also falsifies a Machine scope inside a Lifeline draft.
|
||||
- The nested-parent test uses a real OA Activity parent, refuses an Entity as
|
||||
work ownership, stages exactly one child Activity, then changes the captured
|
||||
parent's kind and proves private preview refuses without changing the raw
|
||||
source state. The implementation validates both the exact parent snapshot
|
||||
and current `can_parent` predicate. This is not a test of every parent family.
|
||||
- The callee regression has one existing ScenarioUse with an empty binding list.
|
||||
Adding a new Activity-backed callee lifeline preserves every original
|
||||
element, relation and diagram and produces the expected
|
||||
`missing_lifeline_binding` warning on that use. Its shared history helper
|
||||
checks model/source Undo, Redo and fresh source reconstruction. This is useful
|
||||
evidence for allowing an incomplete caller; it is not a claim of independently
|
||||
testing multiple callers with nonempty Role mappings.
|
||||
- App Undo/Redo now uses the actual boolean returned by `Document`, calls sync
|
||||
only for a history step, and reports Nothing to undo/redo when appropriate.
|
||||
Its test exercises both an empty history and a real rename through the public
|
||||
`Message::Command` path. Existing `apply()` guards for pending behavior/source
|
||||
remain in front; the existing property-Apply behavior is unchanged. No claim
|
||||
that all Undo/Redo requests are inherently free of property application is
|
||||
introduced.
|
||||
|
||||
### CLI documentation cross-check
|
||||
|
||||
`docs/source-cli.md` and README's explicit `cargo run --locked -p oa-cli --bin
|
||||
arcadia -- check examples/text-first/project.arcadia` example match the final
|
||||
CLI adapter. The example's execution was already verified by root and was not
|
||||
repeated here. The page correctly separates aliases from display names, previews
|
||||
from explicit per-invocation writes, changed-file reports from unchanged captured
|
||||
dependencies, pending recovery from automatic recovery, and source3–7 migration
|
||||
from canonical formatting or detached-file deletion. Root accepted and applied
|
||||
two precision additions during this review: Unicode scalar columns, and
|
||||
`written:false` not implying guaranteed rollback. Readback confirmed both. No
|
||||
new CLI implementation issue or saved-plan/digest requirement was raised.
|
||||
|
||||
### Evidence status
|
||||
|
||||
Read the author's terminal `focused4.log`/status: **22 passed, 0 failed, 653
|
||||
filtered**, 2.04 seconds test execution, exit 0 at 11:59:25 UTC. The matched
|
||||
immutable test executable is SHA-256
|
||||
`6E677F58458B6122EA1886AAC98882640CD9CF260651FE3ECE62BDDA4BE38CC0`, inventory 675.
|
||||
The full suite was running under root at review time; it is not reported passed
|
||||
here. Guide/source-origin corrections above are later deltas and require their
|
||||
own coherent source/test evidence, including the final owner-binding detail.
|
||||
Current source-input manifest, focused logs,
|
||||
and author's revised implementation report remain the build evidence authority;
|
||||
this reviewer executed no desktop tests or native workflow.
|
||||
|
||||
### Final source readback closure
|
||||
|
||||
The author froze the strengthened source and root requested a short final
|
||||
readback. **No remaining material source finding in this bounded delta review.**
|
||||
This closes the pending owner-binding detail above; it does not assert that the
|
||||
new source has completed its later compiled/native gates.
|
||||
|
||||
All four guards now compare the captured owner record against the actual parent
|
||||
draft's `d.owner`/`self.owner`, in addition to the document identity. The 23rd
|
||||
regression includes ordinary/legacy × Back/inactive-existing variants for both
|
||||
Scenario and Work. Each has a valid existing-target control, wrong-document and
|
||||
null-origin refusal, and a borrowed full record from another valid same-layer
|
||||
owner. The latter must fail both final preparation and Source Open while the
|
||||
entire raw recovery snapshot remains unchanged. This is the exact falsifier
|
||||
requested in the preceding handoff, not an unrelated invalid-parent failure.
|
||||
|
||||
For an old unengaged draft, first Source Open creates its missing origin only in
|
||||
a private clone; the clone replaces the parent only after source admission
|
||||
succeeds. It cannot rebind an already engaged missing/mismatched origin. Back is
|
||||
still dismissed by its token before those semantic guards, and parent Cancel
|
||||
remains available. The old guide sentence is absent and the retained-owner
|
||||
creation instruction is present.
|
||||
|
||||
Readback hashes match the author's final freeze:
|
||||
|
||||
| File | SHA-256 |
|
||||
| --- | --- |
|
||||
| `behavior/scenario.rs` | `D12A4B1CAA61C08F69C4D2A64BD15568C4B7158DEA91AAC5A52A58A35ADB863C` |
|
||||
| `behavior/topology.rs` | `D06B2F0FC39B4814E94200297E148F1D4D97E04CB167766030AC9DF18689E3B0` |
|
||||
| `behavior/contextual_source_tests.rs` | `5F05318A6533503B9D6FEBF1EC4DD7256F192394BC1B952A7904C8175BD8DDAE` |
|
||||
| `guide.rs` | `47EEB3CC0A48D5712720096015A08387CD354FB91559B0BD6FA106B5CAC6292C` |
|
||||
|
||||
Paths in this last table are under `crates/oa-desktop/src/`. Root subsequently
|
||||
reported the earlier immutable 675-test artifact passed 675/675 in 448.33 seconds
|
||||
(Gitea #185). That artifact predates these final corrections. The author's
|
||||
focused5, matching GUI/lint and root's native/source oracle remain the appropriate
|
||||
next evidence; no Cargo, rustc, native input or production change was performed
|
||||
by this reviewer during closure.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Independent staged-source authoring evaluator preparation
|
||||
|
||||
Codex-9e8r6t /root/palette_finish,2026-09-11. Root authorized new `harness/staged-source-authoring-contract.rs`, `harness/fixtures/staged-source-authoring/` and this report. No native input, production/desktop edits, Cargo or direct-rustc compilation occurred in this preparation. The desktop implementation owner confirmed that the three selected workflows match the published source/consumer contracts; no created output was consulted.
|
||||
|
||||
The frozen baseline and exact native steps are in the fixture README. Two explicit empty owners keep the three cases focused: an OA OperationalActivity scenario and an SA Functional chain, followed by creation of a new SA actor-owned machine with opt-in view. Activity/lifeline and Function/contribution use separate exact names. Source ownership remains layer-root; lifeline/occurrence ownership remains the selected behavior. No implicit allocation, capability involvement, extra occurrence, sequence link or view is predicted.
|
||||
|
||||
The standalone evaluator constructs complete expected records and validated command batches using only `oa_core`: source+lifeline; source+Action+SetSteps; actor+machine+diagram+Layout. The published first-view geometry is independently specified. The exact source updater supplies expected file placement, includes and trivia retention. Only fresh role UUIDs are discovered; deliberately false role-carrier metadata/geometry in self-check must not contaminate expected fields.
|
||||
|
||||
The `check` command takes a separate original first-commit role carrier for every cumulative stage. Earlier role identities cannot be borrowed again from a later stage's output. Every supplied carrier is itself checked against the appropriate complete expected Project and SourceBundle. Ordinary disk file sets are exact; Undo uses the corrected explicit-origin retained-file rule with no arbitrary detached-file allowance. Reopen additionally supports direct exact comparison against the first accepted/Redo checkpoint.
|
||||
|
||||
Existing immutable CLI `BAD169F8…E3559` ran read-only `check` on the new baseline: exit0, no source writes, exactly three expected warning records (`missing_system`, two `empty_sequence`). Artifact `.local/staged-source-oracle-20260911/baseline-cli-check.json` and its command/exit record preserve that admission result. This verifies the authored fixture's current-source admission only; it does not compile or validate the standalone oracle or accept staged-source creation. Baseline hashes are recorded in the fixture README and embedded source strings will pin exact bytes in the eventual evaluator executable.
|
||||
|
||||
Evaluator self-checks are written but **not executed**: semantic/source fixed points, duplicate command rejection and unchanged model, core-session one Undo/Redo, exact untouched baseline/comment preservation, source binding/owner/geometry falsifiers, prior-stage identity replacement refusal and known/unknown/changed/missing retained file cases. Root must grant a matching-rlib direct-rustc window before any pass is claimed. No native or full release acceptance follows from preparation.
|
||||
|
||||
## Subsequent authorized compilation and evaluator checks
|
||||
|
||||
Root granted a short direct-rustc window before the desktop GUI/Clippy gate. Verified the designated core rlib `.local/target-gnullvm/debug/deps/liboa_core-3e81c616fea1d901.rlib` SHA256 `5018A1FD7286ED9DFEDCBBF5B68B399AD5D143F2A9AAAED3078CFC934C9589C4`, initialized the existing toolchain and ran:
|
||||
|
||||
```powershell
|
||||
rustc --edition 2024 -D warnings --crate-name staged_source_authoring_contract harness/staged-source-authoring-contract.rs --extern oa_core=.local/target-gnullvm/debug/deps/liboa_core-3e81c616fea1d901.rlib -L dependency=.local/target-gnullvm/debug/deps -C linker=clang.exe -o .local/staged-source-oracle-20260911/staged-source-authoring-contract.exe
|
||||
```
|
||||
|
||||
Compilation passed in **7.566s**, finished **12:01:48 UTC**. Compiler lease was immediately returned to the desktop owner before isolated runtime checks. Both `self-check BASE` and `check baseline BASE BASE` passed. All previously listed evaluator falsifiers ran, including stronger separate prior-stage identity pinning. Expected stages have3/4/6 reachable files; baseline has2. This supersedes the preceding preparation-only status without implying any produced native-output acceptance. No generator is necessary: the fixed source fixture itself is the input.
|
||||
|
||||
Executable: `.local/staged-source-oracle-20260911/staged-source-authoring-contract.exe`,20864512 bytes,SHA256 **`967D9BA3C6FB3A7EFB410833903EC94556CA2D48A67D5072C8BB160F40A00F9C`**. Source SHA256 `9EB9DD3868B6CB772F907D16AE02995AD10A16F85C087012C24948E6E6FE775D`. Runtime evidence and manifest are in that same private directory: `build-initial.log` (empty successful diagnostics), `build-initial-result.json`, `self-check-initial.log` (SHA256 `6114C5BF9B75A27B4333E3DE38B3CAB08B976B2F01F3158AD8A7127FF7EE0ABB`), `baseline-check.log` (SHA256 `2D82DF14FB345414E164B57177D5A21C426F65C18EB5EF9E010984A92AD2E731`), `checks-initial-result.json` and `manifest.json`. No baseline or produced model files were mutated.
|
||||
@@ -0,0 +1,635 @@
|
||||
//! Independent contextual-source native oracle. No desktop producer is imported.
|
||||
//! self-check BASE | check STAGE BASE ACTUAL [FIRST_LIFELINE [FIRST_CHAIN [FIRST_MACHINE]]]
|
||||
//! same EXPECTED ACTUAL [UNDO_FROM]
|
||||
use oa_core::{source_project::*, *};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
fs,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
const ACTIVITY: &str = "Assess incident work";
|
||||
const LIFELINE: &str = "Assessment lifeline";
|
||||
const FUNCTION: &str = "Classify request";
|
||||
const CONTRIBUTION: &str = "Classify this request";
|
||||
const ACTOR: &str = "Field rescue team";
|
||||
const MACHINE: &str = "Field team operating modes";
|
||||
const VIEW: &str = "Field team operating modes · states";
|
||||
const SCENARIO: u128 = 0xd1510000000040008000000000000002;
|
||||
const CHAIN: u128 = 0xd1510000000040008000000000000003;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum Stage {
|
||||
Baseline,
|
||||
Lifeline,
|
||||
Chain,
|
||||
Machine,
|
||||
}
|
||||
impl Stage {
|
||||
fn parse(text: &str) -> Self {
|
||||
match text {
|
||||
"baseline" => Self::Baseline,
|
||||
"lifeline" => Self::Lifeline,
|
||||
"chain" => Self::Chain,
|
||||
"machine" => Self::Machine,
|
||||
_ => panic!("Stage must be baseline, lifeline, chain or machine"),
|
||||
}
|
||||
}
|
||||
fn additions(self) -> usize {
|
||||
match self {
|
||||
Self::Baseline => 0,
|
||||
Self::Lifeline => 2,
|
||||
Self::Chain => 4,
|
||||
Self::Machine => 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type DiskSources = BTreeMap<String, Vec<u8>>;
|
||||
fn source_paths(root: &Path, here: &Path, paths: &mut DiskSources) {
|
||||
for entry in fs::read_dir(here).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let kind = entry.file_type().unwrap();
|
||||
assert!(
|
||||
!kind.is_symlink(),
|
||||
"Checkpoint files must be ordinary files"
|
||||
);
|
||||
if kind.is_dir() {
|
||||
source_paths(root, &entry.path(), paths);
|
||||
} else if entry.path().extension().is_some_and(|ext| ext == "arcadia") {
|
||||
assert!(kind.is_file());
|
||||
paths.insert(
|
||||
entry
|
||||
.path()
|
||||
.strip_prefix(root)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.replace('\\', "/"),
|
||||
fs::read(entry.path()).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn load_checkpoint(entry: &Path) -> (CompiledSourceProject, DiskSources) {
|
||||
let files = source_files::load_project(entry, ProjectLimits::default()).unwrap();
|
||||
assert!(
|
||||
!files
|
||||
.diagnostics
|
||||
.iter()
|
||||
.any(|d| d.diagnostic.severity == validation::Severity::Error),
|
||||
"Loader errors: {:?}",
|
||||
files.diagnostics
|
||||
);
|
||||
let raw = files.reachable_bundle();
|
||||
let compiled = compile_bundle(&raw, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(
|
||||
compiled.bundle, raw,
|
||||
"No normalization, migration or missing identity is allowed in saved output"
|
||||
);
|
||||
execute_batch(&compiled.decoded.project, &[]).unwrap();
|
||||
let mut disk = BTreeMap::new();
|
||||
let root = entry.parent().unwrap();
|
||||
source_paths(root, root, &mut disk);
|
||||
(compiled, disk)
|
||||
}
|
||||
fn predicted_disk(reachable: &SourceBundle, undo_from: Option<&DiskSources>) -> DiskSources {
|
||||
let mut files = undo_from.cloned().unwrap_or_default();
|
||||
files.extend(
|
||||
reachable
|
||||
.files
|
||||
.iter()
|
||||
.map(|(path, text)| (path.clone(), text.as_bytes().to_vec())),
|
||||
);
|
||||
files
|
||||
}
|
||||
fn load(entry: &Path) -> CompiledSourceProject {
|
||||
let (compiled, files) = load_checkpoint(entry);
|
||||
assert_eq!(
|
||||
files,
|
||||
predicted_disk(&compiled.bundle, None),
|
||||
"Ordinary checkpoint has unexpected detached source files; Undo needs an explicit origin"
|
||||
);
|
||||
compiled
|
||||
}
|
||||
fn baseline(entry: &Path) -> CompiledSourceProject {
|
||||
let base = load(entry);
|
||||
assert_eq!(
|
||||
base.bundle,
|
||||
SourceBundle {
|
||||
entry: "project.arcadia".into(),
|
||||
files: BTreeMap::from([
|
||||
(
|
||||
"project.arcadia".into(),
|
||||
include_str!("fixtures/staged-source-authoring/base/project.arcadia").into()
|
||||
),
|
||||
(
|
||||
"notes.arcadia".into(),
|
||||
include_str!("fixtures/staged-source-authoring/base/notes.arcadia").into()
|
||||
),
|
||||
])
|
||||
},
|
||||
"Baseline bytes differ from the pre-observation fixture embedded in this executable"
|
||||
);
|
||||
let p = &base.decoded.project;
|
||||
assert_eq!(p.elements.len(), 2);
|
||||
assert!(p.relations.is_empty());
|
||||
assert!(p.diagrams.is_empty());
|
||||
assert_eq!(
|
||||
p.elements[&Id::from_u128(SCENARIO)].name,
|
||||
"Operational assessment"
|
||||
);
|
||||
assert_eq!(p.elements[&Id::from_u128(CHAIN)].name, "System assessment");
|
||||
base
|
||||
}
|
||||
|
||||
struct Roles<'a> {
|
||||
actual: &'a Project,
|
||||
baseline: &'a Project,
|
||||
used: BTreeSet<Id>,
|
||||
}
|
||||
impl Roles<'_> {
|
||||
fn fresh(&mut self, ids: Vec<Id>, role: &str) -> Id {
|
||||
assert_eq!(ids.len(), 1, "Exactly one literal role required: {role}");
|
||||
let id = ids[0];
|
||||
assert_eq!(id.get_version_num(), 4, "Fresh role must be UUIDv4: {role}");
|
||||
assert!(!self.baseline.contains(id));
|
||||
assert!(self.used.insert(id));
|
||||
id
|
||||
}
|
||||
fn element(&mut self, kind: Kind, layer: Layer, name: &str) -> Id {
|
||||
self.fresh(
|
||||
self.actual
|
||||
.elements
|
||||
.values()
|
||||
.filter(|e| e.kind() == kind && e.layer() == layer && e.name == name)
|
||||
.map(|e| e.id)
|
||||
.collect(),
|
||||
name,
|
||||
)
|
||||
}
|
||||
fn view(&mut self, machine: Id) -> Id {
|
||||
self.fresh(
|
||||
self.actual
|
||||
.diagrams
|
||||
.values()
|
||||
.filter(|d| {
|
||||
d.name == VIEW
|
||||
&& d.layer == Layer::Sa
|
||||
&& d.projection == ProjectionKind::StateMachine { machine }
|
||||
})
|
||||
.map(|d| d.id)
|
||||
.collect(),
|
||||
VIEW,
|
||||
)
|
||||
}
|
||||
fn placement(&mut self, view: Id, machine: Id) -> Id {
|
||||
self.fresh(
|
||||
self.actual.diagrams[&view]
|
||||
.nodes
|
||||
.values()
|
||||
.filter(|n| n.element == machine)
|
||||
.map(|n| n.id)
|
||||
.collect(),
|
||||
"first view machine placement",
|
||||
)
|
||||
}
|
||||
}
|
||||
fn element(
|
||||
project: &Project,
|
||||
id: Id,
|
||||
name: &str,
|
||||
parent: Option<Id>,
|
||||
body: ElementBody,
|
||||
) -> Element {
|
||||
Element {
|
||||
id,
|
||||
alias: project.fresh_alias(name, "element", id),
|
||||
name: name.into(),
|
||||
description: String::new(),
|
||||
parent,
|
||||
body,
|
||||
}
|
||||
}
|
||||
fn stage_commands(before: &Project, stage: Stage, roles: &mut Roles<'_>) -> Vec<Command> {
|
||||
match stage {
|
||||
Stage::Baseline => vec![],
|
||||
Stage::Lifeline => {
|
||||
let source = roles.element(Kind::Activity, Layer::Oa, ACTIVITY);
|
||||
let line = roles.element(Kind::Lifeline, Layer::Oa, LIFELINE);
|
||||
vec![
|
||||
Command::CreateElement(element(
|
||||
before,
|
||||
source,
|
||||
ACTIVITY,
|
||||
None,
|
||||
ElementBody::Oa(OaBody::Activity),
|
||||
)),
|
||||
Command::CreateElement(element(
|
||||
before,
|
||||
line,
|
||||
LIFELINE,
|
||||
Some(Id::from_u128(SCENARIO)),
|
||||
ElementBody::shared_in(
|
||||
Layer::Oa,
|
||||
SharedBody::Lifeline {
|
||||
represented: Some(source),
|
||||
},
|
||||
),
|
||||
)),
|
||||
]
|
||||
}
|
||||
Stage::Chain => {
|
||||
let source = roles.element(Kind::Function, Layer::Sa, FUNCTION);
|
||||
let step = roles.element(Kind::Occurrence, Layer::Sa, CONTRIBUTION);
|
||||
vec![
|
||||
Command::CreateElement(element(
|
||||
before,
|
||||
source,
|
||||
FUNCTION,
|
||||
None,
|
||||
ElementBody::Sa(SaBody::Function),
|
||||
)),
|
||||
Command::CreateElement(element(
|
||||
before,
|
||||
step,
|
||||
CONTRIBUTION,
|
||||
Some(Id::from_u128(CHAIN)),
|
||||
ElementBody::shared_in(
|
||||
Layer::Sa,
|
||||
SharedBody::Occurrence {
|
||||
body: OccurrenceBody::Action {
|
||||
action: Some(source),
|
||||
lifeline: None,
|
||||
},
|
||||
precondition: String::new(),
|
||||
postcondition: String::new(),
|
||||
},
|
||||
),
|
||||
)),
|
||||
Command::SetSteps(Id::from_u128(CHAIN), vec![step]),
|
||||
]
|
||||
}
|
||||
Stage::Machine => {
|
||||
let actor = roles.element(Kind::SystemActor, Layer::Sa, ACTOR);
|
||||
let machine = roles.element(Kind::StateMachine, Layer::Sa, MACHINE);
|
||||
let diagram = roles.view(machine);
|
||||
let placement = roles.placement(diagram, machine);
|
||||
let owner = element(before, actor, ACTOR, None, ElementBody::Sa(SaBody::Actor));
|
||||
let record = element(
|
||||
before,
|
||||
machine,
|
||||
MACHINE,
|
||||
Some(actor),
|
||||
ElementBody::shared_in(Layer::Sa, SharedBody::StateMachine),
|
||||
);
|
||||
let p = execute_batch(
|
||||
before,
|
||||
&[
|
||||
Command::CreateElement(owner.clone()),
|
||||
Command::CreateElement(record.clone()),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
let view = Diagram {
|
||||
id: diagram,
|
||||
alias: p.fresh_alias(VIEW, "state_view", diagram),
|
||||
name: VIEW.into(),
|
||||
description: String::new(),
|
||||
layer: Layer::Sa,
|
||||
projection: ProjectionKind::StateMachine { machine },
|
||||
routes: vec![],
|
||||
view_options: Default::default(),
|
||||
nodes: BTreeMap::from([(
|
||||
placement,
|
||||
NodePlacement {
|
||||
id: placement,
|
||||
alias: p.fresh_alias(
|
||||
&format!("{MACHINE} placement"),
|
||||
"placement",
|
||||
placement,
|
||||
),
|
||||
element: machine,
|
||||
position: Position { x: 60., y: 60. },
|
||||
size: Size {
|
||||
width: 336.,
|
||||
height: 104.,
|
||||
},
|
||||
collapsed: false,
|
||||
port_anchors: vec![],
|
||||
},
|
||||
)]),
|
||||
};
|
||||
vec![
|
||||
Command::CreateElement(owner),
|
||||
Command::CreateElement(record),
|
||||
Command::CreateDiagram(view),
|
||||
Command::Layout(diagram),
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
fn predict(
|
||||
base: &CompiledSourceProject,
|
||||
stage: Stage,
|
||||
carriers: &[&Project],
|
||||
) -> CompiledSourceProject {
|
||||
let mut result = base.clone();
|
||||
let mut used = BTreeSet::new();
|
||||
for (index, current) in [Stage::Lifeline, Stage::Chain, Stage::Machine]
|
||||
.into_iter()
|
||||
.filter(|s| *s <= stage)
|
||||
.enumerate()
|
||||
{
|
||||
let mut roles = Roles {
|
||||
actual: carriers[index],
|
||||
baseline: &base.decoded.project,
|
||||
used,
|
||||
};
|
||||
let command = Command::Batch(stage_commands(&result.decoded.project, current, &mut roles));
|
||||
used = roles.used;
|
||||
let plan = prepare_command(&result.decoded.project, &command).unwrap();
|
||||
result = update_bundle_with_identity_map(
|
||||
&result,
|
||||
&plan.project,
|
||||
&plan.identity_map,
|
||||
ProjectLimits::default(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
assert_eq!(
|
||||
result.decoded.project.elements.len(),
|
||||
base.decoded.project.elements.len() + stage.additions()
|
||||
);
|
||||
assert_eq!(
|
||||
result.decoded.project.diagrams.len(),
|
||||
usize::from(stage == Stage::Machine)
|
||||
);
|
||||
assert_eq!(
|
||||
result.decoded.project.relations,
|
||||
base.decoded.project.relations
|
||||
);
|
||||
assert_eq!(result.decoded.project.traces, base.decoded.project.traces);
|
||||
assert_eq!(
|
||||
result.decoded.project.artifact_links,
|
||||
base.decoded.project.artifact_links
|
||||
);
|
||||
result
|
||||
}
|
||||
fn equal(a: &CompiledSourceProject, b: &CompiledSourceProject) -> bool {
|
||||
a.decoded.project == b.decoded.project && a.bundle == b.bundle
|
||||
}
|
||||
fn assert_equal(a: &CompiledSourceProject, b: &CompiledSourceProject) {
|
||||
assert_eq!(
|
||||
a.decoded.project, b.decoded.project,
|
||||
"Complete Project differs"
|
||||
);
|
||||
assert_eq!(a.bundle, b.bundle, "Complete exact SourceBundle differs");
|
||||
}
|
||||
fn test_id(n: u128) -> Id {
|
||||
Id::from_u128(0xd2520000000040008000000000000000 + n)
|
||||
}
|
||||
fn false_carrier(base: &Project) -> Project {
|
||||
let mut p = base.clone();
|
||||
for (n, kind, layer, name) in [
|
||||
(1, Kind::Activity, Layer::Oa, ACTIVITY),
|
||||
(2, Kind::Lifeline, Layer::Oa, LIFELINE),
|
||||
(3, Kind::Function, Layer::Sa, FUNCTION),
|
||||
(4, Kind::Occurrence, Layer::Sa, CONTRIBUTION),
|
||||
(5, Kind::SystemActor, Layer::Sa, ACTOR),
|
||||
(6, Kind::StateMachine, Layer::Sa, MACHINE),
|
||||
] {
|
||||
p.elements.insert(
|
||||
test_id(n),
|
||||
Element {
|
||||
id: test_id(n),
|
||||
alias: format!("false_alias_{n}"),
|
||||
name: name.into(),
|
||||
description: "Never copy this observed metadata".into(),
|
||||
parent: None,
|
||||
body: ElementBody::new(kind, layer).unwrap(),
|
||||
},
|
||||
);
|
||||
}
|
||||
p.diagrams.insert(
|
||||
test_id(7),
|
||||
Diagram {
|
||||
id: test_id(7),
|
||||
alias: "false_view_alias".into(),
|
||||
name: VIEW.into(),
|
||||
description: "Never copy this".into(),
|
||||
layer: Layer::Sa,
|
||||
projection: ProjectionKind::StateMachine {
|
||||
machine: test_id(6),
|
||||
},
|
||||
routes: vec![],
|
||||
view_options: Default::default(),
|
||||
nodes: BTreeMap::from([(
|
||||
test_id(8),
|
||||
NodePlacement {
|
||||
id: test_id(8),
|
||||
alias: "false_placement_alias".into(),
|
||||
element: test_id(6),
|
||||
position: Position { x: -123., y: 987. },
|
||||
size: Size {
|
||||
width: 77.,
|
||||
height: 33.,
|
||||
},
|
||||
collapsed: true,
|
||||
port_anchors: vec![],
|
||||
},
|
||||
)]),
|
||||
},
|
||||
);
|
||||
p
|
||||
}
|
||||
fn self_check(base: &CompiledSourceProject) {
|
||||
let carrier = false_carrier(&base.decoded.project);
|
||||
let mut previous = base.clone();
|
||||
for stage in [Stage::Lifeline, Stage::Chain, Stage::Machine] {
|
||||
let expected = predict(base, stage, &[&carrier; 3]);
|
||||
assert_equal(
|
||||
&expected,
|
||||
&predict(base, stage, &[&expected.decoded.project; 3]),
|
||||
);
|
||||
assert_equal(
|
||||
&expected,
|
||||
&compile_bundle(&expected.bundle, ProjectLimits::default()).unwrap(),
|
||||
);
|
||||
let mut roles = Roles {
|
||||
actual: &carrier,
|
||||
baseline: &base.decoded.project,
|
||||
used: BTreeSet::new(),
|
||||
};
|
||||
let command = Command::Batch(stage_commands(&previous.decoded.project, stage, &mut roles));
|
||||
let mut session = Session::try_new(previous.decoded.project.clone()).unwrap();
|
||||
session.execute(command.clone()).unwrap();
|
||||
assert_eq!(session.project(), &expected.decoded.project);
|
||||
assert!(
|
||||
session.execute(command).is_err(),
|
||||
"Exact repeated creation command must not duplicate identities"
|
||||
);
|
||||
assert_eq!(session.project(), &expected.decoded.project);
|
||||
session.undo();
|
||||
assert_eq!(session.project(), &previous.decoded.project);
|
||||
session.redo();
|
||||
assert_eq!(session.project(), &expected.decoded.project);
|
||||
let mut changed = expected.clone();
|
||||
changed
|
||||
.decoded
|
||||
.project
|
||||
.elements
|
||||
.get_mut(&test_id(1))
|
||||
.unwrap()
|
||||
.description = "unrequested".into();
|
||||
assert!(!equal(&expected, &changed));
|
||||
let mut changed_source = expected.bundle.clone();
|
||||
changed_source
|
||||
.files
|
||||
.get_mut("notes.arcadia")
|
||||
.unwrap()
|
||||
.push_str("// drift\n");
|
||||
let changed = compile_bundle(&changed_source, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(changed.decoded.project, expected.decoded.project);
|
||||
assert!(!equal(&expected, &changed));
|
||||
let committed_disk = predicted_disk(&expected.bundle, None);
|
||||
let undo_disk = predicted_disk(&previous.bundle, Some(&committed_disk));
|
||||
assert!(undo_disk.len() >= previous.bundle.files.len());
|
||||
let mut unknown = undo_disk.clone();
|
||||
unknown.insert("unknown.arcadia".into(), b"// unknown".to_vec());
|
||||
assert_ne!(unknown, undo_disk);
|
||||
let detached: Vec<_> = undo_disk
|
||||
.keys()
|
||||
.filter(|p| !previous.bundle.files.contains_key(*p))
|
||||
.cloned()
|
||||
.collect();
|
||||
assert!(
|
||||
!detached.is_empty(),
|
||||
"Each selected source operation should add a module"
|
||||
);
|
||||
let mut changed = undo_disk.clone();
|
||||
changed.get_mut(&detached[0]).unwrap().push(b' ');
|
||||
assert_ne!(changed, undo_disk);
|
||||
let mut missing = undo_disk.clone();
|
||||
missing.remove(&detached[0]);
|
||||
assert_ne!(missing, undo_disk);
|
||||
println!(
|
||||
"PASS {stage:?}: complete model/source fixed point, false-carrier metadata ignored, repeated-command refusal, one Undo/Redo, comment drift and explicit retained-file falsifiers; {} reachable files",
|
||||
expected.bundle.files.len()
|
||||
);
|
||||
previous = expected;
|
||||
}
|
||||
let expected = predict(base, Stage::Machine, &[&carrier; 3]);
|
||||
let mut wrong = expected.clone();
|
||||
wrong
|
||||
.decoded
|
||||
.project
|
||||
.elements
|
||||
.get_mut(&test_id(2))
|
||||
.unwrap()
|
||||
.body = ElementBody::shared_in(Layer::Oa, SharedBody::Lifeline { represented: None });
|
||||
assert!(!equal(&expected, &wrong));
|
||||
let mut wrong = expected.clone();
|
||||
wrong
|
||||
.decoded
|
||||
.project
|
||||
.elements
|
||||
.get_mut(&test_id(6))
|
||||
.unwrap()
|
||||
.parent = None;
|
||||
assert!(!equal(&expected, &wrong));
|
||||
let mut wrong = expected.clone();
|
||||
wrong
|
||||
.decoded
|
||||
.project
|
||||
.diagrams
|
||||
.get_mut(&test_id(7))
|
||||
.unwrap()
|
||||
.nodes
|
||||
.get_mut(&test_id(8))
|
||||
.unwrap()
|
||||
.position
|
||||
.x += 1.;
|
||||
assert!(!equal(&expected, &wrong));
|
||||
println!(
|
||||
"PASS wrong source binding, machine owner and view geometry rejected; no native acceptance claimed"
|
||||
);
|
||||
let mut changed_prior_role = carrier.clone();
|
||||
let mut changed_activity = changed_prior_role.elements.remove(&test_id(1)).unwrap();
|
||||
changed_activity.id = test_id(91);
|
||||
changed_prior_role
|
||||
.elements
|
||||
.insert(test_id(91), changed_activity);
|
||||
let pinned = predict(base, Stage::Chain, &[&carrier, &changed_prior_role]);
|
||||
assert_equal(&pinned, &predict(base, Stage::Chain, &[&carrier; 3]));
|
||||
assert!(!equal(
|
||||
&pinned,
|
||||
&predict(base, Stage::Chain, &[&changed_prior_role; 3])
|
||||
));
|
||||
println!("PASS earlier-stage role identities remain pinned independently of a later carrier");
|
||||
}
|
||||
fn main() {
|
||||
assert_eq!(SCHEMA_VERSION, 7);
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
match args.get(1).map(String::as_str) {
|
||||
Some("self-check") => {
|
||||
assert_eq!(args.len(), 3);
|
||||
self_check(&baseline(Path::new(&args[2])));
|
||||
}
|
||||
Some("check") => {
|
||||
assert!(
|
||||
args.len() >= 5,
|
||||
"check STAGE BASE ACTUAL [FIRST_LIFELINE [FIRST_CHAIN [FIRST_MACHINE]]]"
|
||||
);
|
||||
let stage = Stage::parse(&args[2]);
|
||||
let stages: Vec<_> = [Stage::Lifeline, Stage::Chain, Stage::Machine]
|
||||
.into_iter()
|
||||
.filter(|s| *s <= stage)
|
||||
.collect();
|
||||
assert_eq!(
|
||||
args.len(),
|
||||
5 + stages.len(),
|
||||
"Supply every stage's original first-commit role carrier separately"
|
||||
);
|
||||
let base = baseline(Path::new(&args[3]));
|
||||
let actual = load(Path::new(&args[4]));
|
||||
let carriers: Vec<_> = args[5..].iter().map(|path| load(Path::new(path))).collect();
|
||||
let projects: Vec<_> = carriers.iter().map(|c| &c.decoded.project).collect();
|
||||
for (index, carrier_stage) in stages.into_iter().enumerate() {
|
||||
assert_equal(&predict(&base, carrier_stage, &projects), &carriers[index]);
|
||||
}
|
||||
let expected = predict(&base, stage, &projects);
|
||||
assert_equal(&expected, &actual);
|
||||
println!(
|
||||
"PASS {stage:?}: complete Project + {} exact source/disk files, original role UUIDs",
|
||||
actual.bundle.files.len()
|
||||
);
|
||||
}
|
||||
Some("same") => {
|
||||
assert!(
|
||||
matches!(args.len(), 4 | 5),
|
||||
"same EXPECTED ACTUAL [UNDO_FROM]"
|
||||
);
|
||||
let expected = load(Path::new(&args[2]));
|
||||
let (actual, disk) = load_checkpoint(Path::new(&args[3]));
|
||||
assert_equal(&expected, &actual);
|
||||
let origin = args
|
||||
.get(4)
|
||||
.map(|path| predicted_disk(&load(Path::new(path)).bundle, None));
|
||||
assert_eq!(
|
||||
disk,
|
||||
predicted_disk(&expected.bundle, origin.as_ref()),
|
||||
"Only exact first-commit retained files are permitted after Undo"
|
||||
);
|
||||
println!(
|
||||
"PASS exact model/identity/{} reachable sources; {} exact disk files ({} proven retained)",
|
||||
actual.bundle.files.len(),
|
||||
disk.len(),
|
||||
disk.len() - actual.bundle.files.len()
|
||||
);
|
||||
}
|
||||
_ => panic!(
|
||||
"self-check BASE | check STAGE BASE ACTUAL [FIRST_LIFELINE [FIRST_CHAIN [FIRST_MACHINE]]] | same EXPECTED ACTUAL [UNDO_FROM]"
|
||||
),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user