Merge tested R6 data workflows into direct scenario workspace
This commit is contained in:
@@ -340,6 +340,7 @@ pub enum Message {
|
||||
FieldShape(String, Value),
|
||||
FieldAppend(String, Value),
|
||||
FieldValuePath(String, crate::data_values::FieldPathKey),
|
||||
FieldValueBrowse(String, Option<crate::data_values::FieldPathKey>, usize),
|
||||
FieldVariant(String, Value),
|
||||
FieldArray(String, Option<usize>, i32),
|
||||
Apply,
|
||||
@@ -1467,6 +1468,18 @@ impl App {
|
||||
self.status = error;
|
||||
}
|
||||
}
|
||||
Message::FieldValueBrowse(path, scope, page) => {
|
||||
if let Some(draft) = &mut self.draft
|
||||
&& draft
|
||||
.value
|
||||
.pointer(&path)
|
||||
.is_some_and(|row| row.get("expression").is_some())
|
||||
{
|
||||
draft
|
||||
.value_browsers
|
||||
.insert(path, crate::forms::ValueBrowser { scope, page });
|
||||
}
|
||||
}
|
||||
Message::FieldValuePath(path, key) => {
|
||||
if let Some(draft) = &mut self.draft
|
||||
&& let Err(error) = draft.value_path(&path, key)
|
||||
@@ -2947,8 +2960,14 @@ impl App {
|
||||
.discovered(&disk.bundle, disk.reachable.clone());
|
||||
self.show_source_file(false);
|
||||
self.source_diagnostics = self.document.compiled().diagnostics.clone();
|
||||
self.status =
|
||||
"Source project opened. Included files and comments are preserved.".into();
|
||||
self.migration = self.document.compiled().decoded.migration.clone();
|
||||
if self.migration.is_some() {
|
||||
self.status = "Imported earlier source schema. Review Model checks; Save all explicitly writes the upgraded source while retaining comments and includes.".into();
|
||||
self.page = Page::Validation;
|
||||
} else {
|
||||
self.status =
|
||||
"Source project opened. Included files and comments are preserved.".into();
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
self.canvas_document = Id::new_v4();
|
||||
@@ -3578,7 +3597,9 @@ fn read_snapshot(path: PathBuf) -> Result<LoadedSnapshot, String> {
|
||||
&& let Some(source_files::DiskExpectation::Bytes(bytes)) =
|
||||
disk.expectations.get(&disk.bundle.entry)
|
||||
&& let Ok(decoded) = persistence::decode_with_report_limited(bytes, LIMITS.model)
|
||||
&& decoded.migration.is_some()
|
||||
// Source1/2 require the historical single-document adapters.
|
||||
// Source3+ must retain its authored bundle and token migration.
|
||||
&& decoded.migration.as_ref().is_some_and(|report| report.from_schema <= 2)
|
||||
{
|
||||
return Ok(LoadedSnapshot::Legacy(
|
||||
path,
|
||||
@@ -3663,6 +3684,97 @@ mod source_project_tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn source3_native_open_preserves_report_comments_nesting_and_save_reopen() {
|
||||
let original = include_str!("../../oa-core/tests/fixtures/v3-data-contract.arcadia");
|
||||
for split in [false, true] {
|
||||
let directory = Directory::new();
|
||||
let path = directory.0.join("project.arcadia");
|
||||
let mut authored = std::collections::BTreeMap::new();
|
||||
if split {
|
||||
let start = original.find("{\n").unwrap() + 2;
|
||||
let end = original.rfind('}').unwrap();
|
||||
authored.insert(
|
||||
"project.arcadia",
|
||||
format!(
|
||||
"{} include \"dictionary.arcadia\";\n}}\n",
|
||||
&original[..start]
|
||||
),
|
||||
);
|
||||
authored.insert("dictionary.arcadia", original[start..end].to_owned());
|
||||
} else {
|
||||
authored.insert("project.arcadia", original.to_owned());
|
||||
}
|
||||
for (file, source) in &authored {
|
||||
std::fs::write(directory.0.join(file), source).unwrap();
|
||||
}
|
||||
let mut app = App::with_project(Project::empty());
|
||||
send(
|
||||
&mut app,
|
||||
Message::Loaded(Ok(Some(read_snapshot(path.clone()).unwrap()))),
|
||||
);
|
||||
assert_eq!(app.migration.as_ref().unwrap().from_schema, 3);
|
||||
assert_eq!(app.page, Page::Validation);
|
||||
assert_eq!(app.path, Some(path.clone()));
|
||||
assert_eq!(app.document.bundle().files.len(), authored.len());
|
||||
assert!(
|
||||
app.dirty(),
|
||||
"accepted source migration needs explicit saving"
|
||||
);
|
||||
for (file, source) in &authored {
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(directory.0.join(file)).unwrap(),
|
||||
*source
|
||||
);
|
||||
}
|
||||
let text = app
|
||||
.document
|
||||
.bundle()
|
||||
.files
|
||||
.values()
|
||||
.cloned()
|
||||
.collect::<String>();
|
||||
assert!(text.contains("// Reused record parameters retain their own identities."));
|
||||
assert!(text.contains("// Frozen authored schema3 compatibility input."));
|
||||
let packet = app
|
||||
.project()
|
||||
.elements
|
||||
.values()
|
||||
.find(|e| e.alias == "packet")
|
||||
.unwrap()
|
||||
.id;
|
||||
let origin = app
|
||||
.project()
|
||||
.elements
|
||||
.values()
|
||||
.find(|e| e.alias == "origin")
|
||||
.unwrap()
|
||||
.id;
|
||||
assert_eq!(
|
||||
app.document.compiled().index.lexical_owners.get(&origin),
|
||||
Some(&packet)
|
||||
);
|
||||
let before = app.document.snapshot();
|
||||
save(&mut app, path.clone()).unwrap();
|
||||
assert!(!app.dirty());
|
||||
for (file, source) in &before.bundle.files {
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(directory.0.join(file)).unwrap(),
|
||||
*source
|
||||
);
|
||||
}
|
||||
let mut reopened = App::with_project(Project::empty());
|
||||
send(
|
||||
&mut reopened,
|
||||
Message::Loaded(Ok(Some(read_snapshot(path).unwrap()))),
|
||||
);
|
||||
assert!(reopened.migration.is_none());
|
||||
assert_eq!(reopened.project(), app.project());
|
||||
assert_eq!(reopened.document.bundle(), app.document.bundle());
|
||||
assert!(!reopened.dirty());
|
||||
}
|
||||
}
|
||||
|
||||
fn pending_journal(directory: &Directory, before: Option<&str>) -> (PathBuf, PathBuf) {
|
||||
let path = directory.0.join("project.arcadia");
|
||||
let journal = directory.0.join(".arcadia-save-project.arcadia.journal");
|
||||
|
||||
@@ -11,10 +11,11 @@ pub struct FieldPathKey {
|
||||
pub struct FieldPathChoice {
|
||||
pub key: FieldPathKey,
|
||||
pub label: String,
|
||||
pub picker_label: String,
|
||||
}
|
||||
impl std::fmt::Display for FieldPathChoice {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&self.label)
|
||||
f.write_str(&self.picker_label)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +50,7 @@ fn named_choice(project: &Project, entry: data::CarriedFieldPath) -> FieldPathCh
|
||||
.map(|e| format!("{} (@{})", e.name, e.alias))
|
||||
.unwrap_or_else(|| id.to_string())
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" → ");
|
||||
.collect::<Vec<_>>();
|
||||
let direction =
|
||||
if data::item_mechanism(project, entry.item) == Some(ExchangeMechanism::Operation) {
|
||||
match entry.direction {
|
||||
@@ -63,54 +63,97 @@ fn named_choice(project: &Project, entry: data::CarriedFieldPath) -> FieldPathCh
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let terminal = qualified
|
||||
.last()
|
||||
.expect("A field path always has a terminal");
|
||||
let owner_path = qualified[..qualified.len() - 1].join(" → ");
|
||||
let picker_label = format!(
|
||||
"{terminal}{direction} — {}{}",
|
||||
project.named(entry.item),
|
||||
if owner_path.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!(" / {owner_path}")
|
||||
},
|
||||
);
|
||||
FieldPathChoice {
|
||||
key: FieldPathKey {
|
||||
path: entry.path,
|
||||
field: entry.field,
|
||||
},
|
||||
label: format!("{} / {qualified}{direction}", project.named(entry.item)),
|
||||
label: format!(
|
||||
"{} / {}{direction}",
|
||||
project.named(entry.item),
|
||||
qualified.join(" → ")
|
||||
),
|
||||
picker_label,
|
||||
}
|
||||
}
|
||||
|
||||
// A bounded picker must expose its distinguishing field before a long path.
|
||||
// Keep the full address separately for the wrapping detail text.
|
||||
fn sorted_choices(mut choices: Vec<FieldPathChoice>) -> Vec<FieldPathChoice> {
|
||||
choices.sort_by_cached_key(|choice| choice.picker_label.to_lowercase());
|
||||
choices
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn choices(
|
||||
project: &Project,
|
||||
exchange: &Relation,
|
||||
phase: &MessageKind,
|
||||
) -> Result<Vec<FieldPathChoice>, String> {
|
||||
Ok(data::try_carried_field_paths(project, exchange)?
|
||||
.into_iter()
|
||||
.filter(|entry| phase_allows(project, entry, phase))
|
||||
.map(|entry| named_choice(project, entry))
|
||||
.collect())
|
||||
Ok(sorted_choices(
|
||||
data::try_carried_field_paths(project, exchange)?
|
||||
.into_iter()
|
||||
.filter(|entry| phase_allows(project, entry, phase))
|
||||
.map(|entry| named_choice(project, entry))
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Direct carried fields only: an unrelated deep branch must not prevent
|
||||
/// browsing a root field. Preserve the core resolver's first carried owner.
|
||||
pub fn roots(project: &Project, exchange: &Relation, phase: &MessageKind) -> Vec<FieldPathChoice> {
|
||||
let mut seen = std::collections::BTreeSet::new();
|
||||
exchange
|
||||
.body
|
||||
.items()
|
||||
.iter()
|
||||
.flat_map(|item| {
|
||||
data::effective_fields(project, *item)
|
||||
.into_iter()
|
||||
.filter_map(|field| {
|
||||
let SharedBody::DataField { direction, .. } = field.shared()? else {
|
||||
return None;
|
||||
};
|
||||
Some(data::CarriedFieldPath {
|
||||
item: *item,
|
||||
path: vec![],
|
||||
field: field.id,
|
||||
direction: *direction,
|
||||
sorted_choices(
|
||||
exchange
|
||||
.body
|
||||
.items()
|
||||
.iter()
|
||||
.flat_map(|item| {
|
||||
data::effective_fields(project, *item)
|
||||
.into_iter()
|
||||
.filter_map(|field| {
|
||||
let SharedBody::DataField { direction, .. } = field.shared()? else {
|
||||
return None;
|
||||
};
|
||||
Some(data::CarriedFieldPath {
|
||||
item: *item,
|
||||
path: vec![],
|
||||
field: field.id,
|
||||
direction: *direction,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.filter(|entry| seen.insert(entry.field))
|
||||
.filter(|entry| phase_allows(project, entry, phase))
|
||||
.map(|entry| named_choice(project, entry))
|
||||
.collect()
|
||||
})
|
||||
.filter(|entry| seen.insert(entry.field))
|
||||
.filter(|entry| phase_allows(project, entry, phase))
|
||||
.map(|entry| named_choice(project, entry))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Browse one record at a time, including explicitly chosen recursive hops.
|
||||
pub fn at_scope(
|
||||
project: &Project,
|
||||
exchange: &Relation,
|
||||
phase: &MessageKind,
|
||||
scope: Option<&FieldPathKey>,
|
||||
) -> Result<Vec<FieldPathChoice>, String> {
|
||||
match scope {
|
||||
Some(key) => children(project, exchange, phase, key),
|
||||
None => Ok(roots(project, exchange, phase)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve authored finite paths as well as the finite representative picker list.
|
||||
@@ -166,20 +209,22 @@ pub fn children(
|
||||
}
|
||||
let mut path = key.path.clone();
|
||||
path.push(key.field);
|
||||
Ok(data::effective_fields(project, *record)
|
||||
.into_iter()
|
||||
.map(|field| {
|
||||
named_choice(
|
||||
project,
|
||||
data::CarriedFieldPath {
|
||||
item: entry.item,
|
||||
path: path.clone(),
|
||||
field: field.id,
|
||||
direction: entry.direction,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect())
|
||||
Ok(sorted_choices(
|
||||
data::effective_fields(project, *record)
|
||||
.into_iter()
|
||||
.map(|field| {
|
||||
named_choice(
|
||||
project,
|
||||
data::CarriedFieldPath {
|
||||
item: entry.item,
|
||||
path: path.clone(),
|
||||
field: field.id,
|
||||
direction: entry.direction,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -482,4 +527,33 @@ pub(crate) mod tests {
|
||||
.contains("128")
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn recursive_picker_starts_with_distinct_leaf_names_and_sorts_them() {
|
||||
let (f, next) = recursive_payload();
|
||||
let exchange = &f.project.relations[&f.exchange];
|
||||
let context = FieldPathKey {
|
||||
path: vec![f.origin, next, next],
|
||||
field: next,
|
||||
};
|
||||
let visible = children(&f.project, exchange, &MessageKind::Call, &context).unwrap();
|
||||
let leaf = visible
|
||||
.iter()
|
||||
.find(|choice| choice.key.field == f.leaf)
|
||||
.unwrap();
|
||||
assert!(leaf.to_string().starts_with("latitude (@latitude)"));
|
||||
assert!(leaf.label.contains("origin (@origin) → next (@next)"));
|
||||
assert!(
|
||||
visible.windows(2).all(
|
||||
|pair| pair[0].to_string().to_lowercase() <= pair[1].to_string().to_lowercase()
|
||||
)
|
||||
);
|
||||
assert_ne!(
|
||||
visible[0].to_string().chars().take(24).collect::<String>(),
|
||||
visible[1].to_string().chars().take(24).collect::<String>()
|
||||
);
|
||||
assert_eq!(
|
||||
resolve(&f.project, exchange, &MessageKind::Call, &leaf.key),
|
||||
Some(leaf.clone())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,12 @@ pub struct Input {
|
||||
pub raw: String,
|
||||
pub editor: text_editor::Content,
|
||||
}
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ValueBrowser {
|
||||
pub scope: Option<crate::data_values::FieldPathKey>,
|
||||
pub page: usize,
|
||||
}
|
||||
|
||||
pub struct Draft {
|
||||
pub kind: RecordKind,
|
||||
pub original: Id,
|
||||
@@ -40,6 +46,7 @@ pub struct Draft {
|
||||
pub inputs: BTreeMap<String, Input>,
|
||||
pub exact_strings: bool,
|
||||
port_contract_drafts: BTreeMap<String, Value>,
|
||||
pub value_browsers: BTreeMap<String, ValueBrowser>,
|
||||
}
|
||||
|
||||
impl Draft {
|
||||
@@ -77,11 +84,14 @@ impl Draft {
|
||||
inputs: BTreeMap::new(),
|
||||
exact_strings: false,
|
||||
port_contract_drafts: BTreeMap::new(),
|
||||
value_browsers: BTreeMap::new(),
|
||||
};
|
||||
draft.rebuild();
|
||||
Some(draft)
|
||||
}
|
||||
fn rebuild(&mut self) {
|
||||
// Array/variant edits can change the meaning of a row path.
|
||||
self.value_browsers.clear();
|
||||
self.inputs.clear();
|
||||
fn visit(value: &Value, path: &str, out: &mut BTreeMap<String, Input>) {
|
||||
match value {
|
||||
@@ -710,10 +720,15 @@ fn reference_ids(draft: &Draft, project: &Project, path: &str) -> Vec<Id> {
|
||||
..
|
||||
},
|
||||
..
|
||||
} => project
|
||||
.relations
|
||||
.get(id)
|
||||
.and_then(|r| crate::data_values::choices(project, r, message_kind).ok()),
|
||||
} => project.relations.get(id).and_then(|r| {
|
||||
let scope = address_path.split_last().map(|(&field, path)| {
|
||||
crate::data_values::FieldPathKey {
|
||||
path: path.to_vec(),
|
||||
field,
|
||||
}
|
||||
});
|
||||
crate::data_values::at_scope(project, r, message_kind, scope.as_ref()).ok()
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_default()
|
||||
|
||||
@@ -330,97 +330,152 @@ fn message_value<'a>(
|
||||
} => project.relations.get(id).map(|r| (r, message_kind)),
|
||||
_ => None,
|
||||
});
|
||||
let choices = context
|
||||
.map(|(r, phase)| crate::data_values::choices(project, r, phase))
|
||||
.unwrap_or_else(|| Ok(vec![]));
|
||||
let mut out = column![text("Qualified carried field").size(11).color(style::MUTED)].spacing(6);
|
||||
match choices {
|
||||
Err(error) => out = out.push(text(error).size(11).color(style::MUTED)),
|
||||
Ok(mut choices) => {
|
||||
let current_key = current.as_ref().map(|v| crate::data_values::FieldPathKey {
|
||||
path: v.path.clone(),
|
||||
field: v.field,
|
||||
});
|
||||
let mut selected = current_key
|
||||
let current_key = current
|
||||
.as_ref()
|
||||
.map(|value| crate::data_values::FieldPathKey {
|
||||
path: value.path.clone(),
|
||||
field: value.field,
|
||||
});
|
||||
let selected = context.and_then(|(exchange, phase)| {
|
||||
current_key
|
||||
.as_ref()
|
||||
.and_then(|key| crate::data_values::resolve(project, exchange, phase, key))
|
||||
});
|
||||
let browser = draft
|
||||
.value_browsers
|
||||
.get(path)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| ValueBrowser {
|
||||
scope: selected
|
||||
.as_ref()
|
||||
.and_then(|key| choices.iter().find(|c| &c.key == key))
|
||||
.cloned()
|
||||
.or_else(|| {
|
||||
context.and_then(|(r, phase)| {
|
||||
current_key
|
||||
.as_ref()
|
||||
.and_then(|key| crate::data_values::resolve(project, r, phase, key))
|
||||
})
|
||||
});
|
||||
if let Some(choice) = &selected
|
||||
&& !choices.iter().any(|c| c.key == choice.key)
|
||||
{
|
||||
choices.push(choice.clone());
|
||||
}
|
||||
if selected.is_none()
|
||||
&& let Some(key) = current_key.clone()
|
||||
&& !key.field.is_nil()
|
||||
{
|
||||
out = out.push(text("Current address needs review. Choose an explicit path to resolve a legacy, ambiguous or incompatible value.").size(11).color(style::MUTED));
|
||||
let retained = crate::data_values::FieldPathChoice {
|
||||
label: format!(
|
||||
"Current address · {} / {}",
|
||||
key.path
|
||||
.iter()
|
||||
.map(|id| project.named(*id))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" → "),
|
||||
project.named(key.field)
|
||||
),
|
||||
key,
|
||||
};
|
||||
selected = Some(retained.clone());
|
||||
choices.push(retained);
|
||||
}
|
||||
let owned = path.to_owned();
|
||||
out = out.push(
|
||||
pick_list(choices, selected, move |choice| {
|
||||
Message::FieldValuePath(owned.clone(), choice.key)
|
||||
})
|
||||
.placeholder("Choose a carried field path…")
|
||||
.text_size(12)
|
||||
.padding(8)
|
||||
.width(Fill),
|
||||
);
|
||||
}
|
||||
.and_then(|choice| crate::data_values::parent(&choice.key)),
|
||||
page: 0,
|
||||
});
|
||||
let mut out = column![text("Qualified carried field").size(11).color(style::MUTED)].spacing(6);
|
||||
if let Some(choice) = &selected {
|
||||
out = out.push(text(choice.label.clone()).size(11));
|
||||
} else if let Some(key) = ¤t_key
|
||||
&& !key.field.is_nil()
|
||||
{
|
||||
out = out.push(
|
||||
text(format!(
|
||||
"Current address needs review: {} / {}. Choose an explicit field.",
|
||||
key.path
|
||||
.iter()
|
||||
.map(|id| project.named(*id))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" → "),
|
||||
project.named(key.field)
|
||||
))
|
||||
.size(11)
|
||||
.color(style::MUTED),
|
||||
);
|
||||
}
|
||||
if let (Some((exchange, phase)), Some(current)) = (context, current) {
|
||||
let key = crate::data_values::FieldPathKey {
|
||||
path: current.path,
|
||||
field: current.field,
|
||||
};
|
||||
if crate::data_values::resolve(project, exchange, phase, &key).is_some() {
|
||||
if let Some(parent) = crate::data_values::parent(&key) {
|
||||
out = out.push(
|
||||
button(text("Up to enclosing field").size(11))
|
||||
if let Some((exchange, phase)) = context {
|
||||
let location = browser
|
||||
.scope
|
||||
.as_ref()
|
||||
.and_then(|key| crate::data_values::resolve(project, exchange, phase, key))
|
||||
.map(|choice| choice.label)
|
||||
.unwrap_or_else(|| "Root carried fields".into());
|
||||
out = out.push(
|
||||
text(format!("Browse: {location}"))
|
||||
.size(11)
|
||||
.color(style::MUTED),
|
||||
);
|
||||
if let Some(scope) = &browser.scope {
|
||||
let mut navigation = row![button(text("↑ Up").size(11)).style(style::nav).on_press(
|
||||
Message::FieldValueBrowse(path.into(), crate::data_values::parent(scope), 0)
|
||||
)]
|
||||
.spacing(4);
|
||||
if !scope.path.is_empty() {
|
||||
navigation = navigation.push(
|
||||
button(text("Root fields").size(11))
|
||||
.style(style::nav)
|
||||
.on_press(Message::FieldValuePath(path.into(), parent)),
|
||||
.on_press(Message::FieldValueBrowse(path.into(), None, 0)),
|
||||
);
|
||||
}
|
||||
match crate::data_values::children(project, exchange, phase, &key) {
|
||||
Ok(children) if !children.is_empty() => {
|
||||
let path = path.to_owned();
|
||||
out = out.push(navigation);
|
||||
}
|
||||
match crate::data_values::at_scope(project, exchange, phase, browser.scope.as_ref()) {
|
||||
Ok(choices) => {
|
||||
let count = choices.len();
|
||||
let (visible, page, pages) = field_page(choices, browser.page);
|
||||
// Selection detail stays visible independently of browser location/page.
|
||||
let visible_selection = selected
|
||||
.clone()
|
||||
.filter(|choice| visible.iter().any(|c| c.key == choice.key));
|
||||
let owned = path.to_owned();
|
||||
out = out.push(
|
||||
pick_list(visible, visible_selection, move |choice| {
|
||||
Message::FieldValuePath(owned.clone(), choice.key)
|
||||
})
|
||||
.placeholder("Choose a field here…")
|
||||
.text_size(12)
|
||||
.padding(8)
|
||||
.width(Fill),
|
||||
);
|
||||
if pages > 1 {
|
||||
out = out.push(
|
||||
pick_list(
|
||||
children,
|
||||
None::<crate::data_values::FieldPathChoice>,
|
||||
move |choice| Message::FieldValuePath(path.clone(), choice.key),
|
||||
)
|
||||
.placeholder("Choose a field inside this record…")
|
||||
.text_size(12)
|
||||
.padding(8)
|
||||
.width(Fill),
|
||||
row![
|
||||
button(text("Previous").size(11))
|
||||
.style(style::nav)
|
||||
.on_press_maybe((page > 0).then(|| Message::FieldValueBrowse(
|
||||
path.into(),
|
||||
browser.scope.clone(),
|
||||
page - 1
|
||||
))),
|
||||
text(format!("{} / {pages} · {count} fields", page + 1)).size(11),
|
||||
button(text("Next").size(11))
|
||||
.style(style::nav)
|
||||
.on_press_maybe((page + 1 < pages).then(|| {
|
||||
Message::FieldValueBrowse(
|
||||
path.into(),
|
||||
browser.scope.clone(),
|
||||
page + 1,
|
||||
)
|
||||
}))
|
||||
]
|
||||
.spacing(4)
|
||||
.align_y(iced::Alignment::Center),
|
||||
);
|
||||
} else if count == 0 {
|
||||
out = out.push(
|
||||
text("No compatible fields at this location.")
|
||||
.size(11)
|
||||
.color(style::MUTED),
|
||||
);
|
||||
}
|
||||
Err(error) => out = out.push(text(error).size(11).color(style::MUTED)),
|
||||
_ => {}
|
||||
}
|
||||
Err(error) => out = out.push(text(error).size(11).color(style::MUTED)),
|
||||
}
|
||||
if let Some(choice) = &selected
|
||||
&& browser.scope.as_ref() != Some(&choice.key)
|
||||
&& crate::data_values::children(project, exchange, phase, &choice.key)
|
||||
.is_ok_and(|children| !children.is_empty())
|
||||
{
|
||||
out = out.push(
|
||||
button(
|
||||
text(format!(
|
||||
"Browse fields in {} →",
|
||||
project.named(choice.key.field)
|
||||
))
|
||||
.size(11),
|
||||
)
|
||||
.style(style::nav)
|
||||
.on_press(Message::FieldValueBrowse(
|
||||
path.into(),
|
||||
Some(choice.key.clone()),
|
||||
0,
|
||||
)),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
out = out.push(
|
||||
text("Choose a message exchange to browse its carried fields.")
|
||||
.size(11)
|
||||
.color(style::MUTED),
|
||||
);
|
||||
}
|
||||
if let Some(expression) = value.get("expression") {
|
||||
out = out.push(super::property(
|
||||
@@ -435,6 +490,25 @@ fn message_value<'a>(
|
||||
out.into()
|
||||
}
|
||||
|
||||
const FIELDS_PER_PAGE: usize = 24;
|
||||
|
||||
fn field_page(
|
||||
choices: Vec<crate::data_values::FieldPathChoice>,
|
||||
requested: usize,
|
||||
) -> (Vec<crate::data_values::FieldPathChoice>, usize, usize) {
|
||||
let pages = choices.len().div_ceil(FIELDS_PER_PAGE).max(1);
|
||||
let page = requested.min(pages - 1);
|
||||
(
|
||||
choices
|
||||
.into_iter()
|
||||
.skip(page * FIELDS_PER_PAGE)
|
||||
.take(FIELDS_PER_PAGE)
|
||||
.collect(),
|
||||
page,
|
||||
pages,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -490,6 +564,25 @@ mod tests {
|
||||
format!("{path}/expression"),
|
||||
"newly typed".into(),
|
||||
));
|
||||
let before_browse = app.draft.as_ref().unwrap().materialize().unwrap();
|
||||
for (scope, page) in [
|
||||
(None, 0),
|
||||
(
|
||||
Some(crate::data_values::FieldPathKey {
|
||||
path: vec![f.origin],
|
||||
field: next,
|
||||
}),
|
||||
999,
|
||||
),
|
||||
] {
|
||||
let _ = app.update(Message::FieldValueBrowse(path.into(), scope, page));
|
||||
let _ = super::super::view(app.draft.as_ref().unwrap(), app.project());
|
||||
assert_eq!(
|
||||
app.draft.as_ref().unwrap().materialize().unwrap(),
|
||||
before_browse
|
||||
);
|
||||
assert_eq!(app.project(), &f.project);
|
||||
}
|
||||
let _ = app.update(Message::FieldValuePath(
|
||||
path.into(),
|
||||
crate::data_values::FieldPathKey {
|
||||
@@ -553,6 +646,43 @@ mod tests {
|
||||
let _ = super::super::view(app.draft.as_ref().unwrap(), app.project());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn field_browser_pages_every_direct_field_without_flattening_other_records() {
|
||||
let f = crate::data_values::tests::wide_payload();
|
||||
let exchange = &f.project.relations[&f.exchange];
|
||||
let roots =
|
||||
crate::data_values::at_scope(&f.project, exchange, &MessageKind::Call, None).unwrap();
|
||||
assert!(roots.len() > FIELDS_PER_PAGE);
|
||||
assert!(roots.iter().all(|choice| choice.key.path.is_empty()));
|
||||
let scope = crate::data_values::FieldPathKey {
|
||||
path: vec![],
|
||||
field: f.origin,
|
||||
};
|
||||
let children =
|
||||
crate::data_values::at_scope(&f.project, exchange, &MessageKind::Call, Some(&scope))
|
||||
.unwrap();
|
||||
assert!(children.len() > FIELDS_PER_PAGE);
|
||||
assert!(
|
||||
children
|
||||
.iter()
|
||||
.all(|choice| choice.key.path == vec![f.origin])
|
||||
);
|
||||
for choices in [roots, children] {
|
||||
let (_, _, pages) = field_page(choices.clone(), 0);
|
||||
let visited: Vec<_> = (0..pages)
|
||||
.flat_map(|page| {
|
||||
let (visible, actual, _) = field_page(choices.clone(), page);
|
||||
assert_eq!(actual, page);
|
||||
assert!(visible.len() <= FIELDS_PER_PAGE);
|
||||
visible
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(visited, choices);
|
||||
assert_eq!(field_page(choices, usize::MAX).1, pages - 1);
|
||||
}
|
||||
assert_eq!(field_page(vec![], usize::MAX), (vec![], 0, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric_bound_drafts_keep_partial_and_full_precision_values_out_of_accepted_state() {
|
||||
let mut p = Project::empty();
|
||||
|
||||
@@ -63,3 +63,9 @@ State camera/tool lifetime follows effective machine and diagram identity, even
|
||||
when selection changes through Catalog or Layer outside Behavior. Reset only on
|
||||
actual context change; preserve same-view return. Independent review reproduced
|
||||
the leak and native Windows/Linux tests verified the correction in316dc55.
|
||||
|
||||
- Carried-value property browsing follows one exact record scope at a time, with
|
||||
bounded pages and a separate read-only browser location. Flattened representative
|
||||
paths were proven ambiguous in native recursive/reused data. Browsing does not
|
||||
change the selected field or expression; choosing a field remains an explicit
|
||||
draft edit through the ordinary validated command. No persistent browser schema.
|
||||
|
||||
+44
-32
@@ -91,23 +91,17 @@ Dedicated target D:/CodexBuilds/Capella2-data-target. Contract freeze is schema/
|
||||
with full data payload and dictionary slices together; existing typed ports remain.
|
||||
See release-data-implementation.md and release-data-contract.md in that checkout.
|
||||
|
||||
Core is committed0b58107; source/migration1230ab8. Root API/docs are integrated
|
||||
on the same working tree; desktop remains in flight and R6 is not accepted.
|
||||
Core15 R6 +28workflow tests passed again after final allocation-arrow suppression.
|
||||
Linux0b58107 full core307 tests passed (one explicit probe ignored by default),
|
||||
with strict all-target core Clippy. Earlier13ports/14scenarios and115 source/lib
|
||||
tests also passed. Desktop final257 tests and strict all-target Clippy pass;
|
||||
optimized Windows desktop build b403039 passed. Its SHA256 is recorded in the R6 verification note; native acceptance remains pending.
|
||||
R6 core/source/desktop are frozen at ab661f2. Full Windows607 tests and Linux610
|
||||
tests pass (one explicit benchmark ignored on each platform); strict workspace
|
||||
all-target Clippy passes on both. Optimized desktop/server Linux build also passed.
|
||||
Windows desktop261 tests include the bounded scenario value editor. Exact logs,
|
||||
binaries and runtime evidence: release-data-verification.md.
|
||||
|
||||
Root41 server tests passed; a fourth R6 HTTP workflow now also passes, alongside all4 data HTTP tests and strict server Clippy. The original3 actual HTTP workflows for the published
|
||||
data example, protocol/artifact identity, atomic rejected defaults, query/export,
|
||||
reidentify/delete/restart, source3 bundle migration reports and old coupled3
|
||||
envelope upgrade without write/revision. Tests exposed dropped bundle reports and
|
||||
rejected legitimate old source/model pairs; both root fixes passed retest.
|
||||
Strict reST HTML generation and81 OpenAPI schema definitions passed. Actual frozen
|
||||
server32033FFE imported the published example; its complete Project/StoredProject
|
||||
responses passed served/current JSON Schema validation and obsolete shapes rejected.
|
||||
Evidence: api-r6-contract and r6-server-tests-after.log under the release directory.
|
||||
All4 R6 actual HTTP workflows pass, covering data protocols/artifact identity,
|
||||
rejected defaults, qualified Call/Reply paths, validation locations, source edits,
|
||||
reidentification, source3 migration and restart persistence. The published example's
|
||||
actual server responses passed served/local OpenAPI validation; obsolete shapes
|
||||
reject. Strict reST rendering and81 OpenAPI schemas passed.
|
||||
|
||||
Independent core review found association transition closure pulling unrelated
|
||||
types and missing empty-enum warning; both corrected and focused tests passed.
|
||||
@@ -121,14 +115,24 @@ pages replaces unbounded inherited rows; recursive paths support explicit drill-
|
||||
and imported finite paths; same-phase styles/same-exchange reselection preserve
|
||||
valid drafts. Read-only follow-up found no new path/style defect. Paging resets
|
||||
only on actual layer/document changes; its regression failed before and passes now.
|
||||
Root found another unresolved scale issue: scenario creation still enumerates every
|
||||
carried field into both a dropdown and individual input rows. A bounded focused value editor is now implemented and under automated/independent review; actual native operation remains required before R6 acceptance.
|
||||
The bounded scenario editor replaces whole-recursion enumeration and per-field
|
||||
inputs with24-row browsing and a single focused value draft. The reply call picker
|
||||
no longer filters alternative calls using values belonging to the old exchange.
|
||||
Automated and independent checks pass; native scenario checks are next.
|
||||
|
||||
Current ownership: drawing_correctness owns desktop except root-owned guide.rs and
|
||||
the dedicated Windows Cargo target. state_architecture_review independently reviews
|
||||
R6 spec/API consistency; its data_view.rs ownership has ended. data_core runs an
|
||||
isolated R3 typed-baseline experiment; Linux R6 core checkout is idle and verified.
|
||||
Root owns API/OpenAPI/reST, docs, integration and native input. No concurrent writers.
|
||||
Root exclusively operates native R6. The Windows13-object data model has saved
|
||||
native bounds/default repair, a typed physical flow/field, allocation protocol
|
||||
edit, allocation removal/Undo, and inherited-owner navigation. Association endpoint
|
||||
labels/selectability were exercised. The1100x700 data layout has been inspected.
|
||||
A separate53-object recursive-operation fixture was prepared with core APIs and
|
||||
round-tripped for upcoming native scenario trials; fixture construction is not
|
||||
claimed as native authoring. See the verification note for remaining gates.
|
||||
|
||||
Parallel isolated work: drawing_correctness implements direct scenario gestures in
|
||||
Capella2-scenario-direct. data_core owns typed semantic review core and
|
||||
state_architecture_review owns source5/migration in Capella2-semantic-review.
|
||||
The typed facet C design won the bounded experiment/criticism round; its production
|
||||
plan and decision are recorded in that checkout. No overlapping writers or targets.
|
||||
|
||||
1. State evidence is committed and main fast-forwarded to a8f451e; DATA received
|
||||
the same evidence in c5276b1. Finish native data-authoring acceptance and bounded
|
||||
@@ -136,8 +140,8 @@ Root owns API/OpenAPI/reST, docs, integration and native input. No concurrent wr
|
||||
2. Finish R6 core/source/desktop, integrate actual REST/schema/reST, independent
|
||||
semantic/correctness/UX review, Windows/Linux checks and real data authoring.
|
||||
3. Implement R3 typed semantic drift/reconciliation after R6 freezes. Current
|
||||
baselines/reconciliation only cover prose. Prefer historical typed-body snapshots
|
||||
and finite proposals; avoid a duplicate recursive semantic schema without evidence.
|
||||
baselines/reconciliation only cover prose. Use the experimentally selected typed facet review design C; the semantic
|
||||
integration checkout records the full scope and source5 migration plan.
|
||||
4. Complete direct scenario/process gestures, persistent coverage/filters,
|
||||
Home/recent/recovery, hosted desktop ETag workflows and offline guidance.
|
||||
5. Fresh final requirements/domain/correctness/native UX/architecture review; full
|
||||
@@ -145,13 +149,11 @@ Root owns API/OpenAPI/reST, docs, integration and native input. No concurrent wr
|
||||
|
||||
## Environment and native ownership
|
||||
|
||||
Native input is paused after physical Escape; no R6 native trial has run.
|
||||
Root exclusively owns native input. Latest saved Windows trial is window1706782,
|
||||
ui-state-navigation-windows,49objects/28links/1 expected missing-owner warning.
|
||||
Linux navigation trial3148598 closed normally, exec46107 exit0; baseline Linux
|
||||
trial721472 also closed normally, exec72680 exit0. Independent Windows3672536 is
|
||||
saved at1100x700. Older root drawing windows are saved. Re-inventory before input.
|
||||
Protected user7210312/6228978 were absent; do not reset/save/close if they return.
|
||||
The user explicitly reauthorized native testing after Escape. Root's f5467e5 R6
|
||||
window3476204 and exec93768 closed normally after verified source migration and
|
||||
55-object recursive scenario reopen; no runtime output. The property-browser
|
||||
replacement build is running. Original Capella is present. Older protected user7210312/6228978 were absent;
|
||||
do not reset/save/close them if they return. Re-inventory before switching apps.
|
||||
|
||||
Evidence: D:/CodexBuilds/Capella2-release1-01a06e2e. State source checkout/target:
|
||||
D:/CodexBuilds/Capella2-state-integration and -target. Linux source/target:
|
||||
@@ -162,3 +164,13 @@ Windows: cargo test --locked --workspace; cargo clippy --locked --workspace
|
||||
--all-targets -- -D warnings; cargo build --locked -p oa-desktop -p oa-server.
|
||||
WSL Ubuntu24.04 uses target/linux-cargo.toml and Mesa software Vulkan for native
|
||||
WSLg. No remote push or usage reset authorized. No broad recursive target deletion.
|
||||
|
||||
Latest R6 checkpoint: Windows264 desktop tests and strict Clippy pass for the
|
||||
one-record property browser; optimized build/native retest pending. Paging and
|
||||
location changes retain accepted model and typed expressions. f5467e5 Windows
|
||||
and Linux263 desktop tests, strict Clippy and optimized release passed. Native
|
||||
Windows source3 migration preserved comments/nesting through explicit Save All
|
||||
and clean source4 reopen. Native recursive55-object scenario values and paired
|
||||
Call/Reply history were verified; flat property paths prompted the latest fix.
|
||||
Linux native R6 workflows and final independent browser review remain. See
|
||||
release-data-verification.md. Main remains a8f451e; R6 is not yet accepted.
|
||||
|
||||
+12
-8
@@ -39,9 +39,13 @@ requires native workflows, semantic evaluators and fresh independent review.
|
||||
whole-model equality or flat reformatting. Independent counterexamples were fixed.
|
||||
- R3 existing-target reconciliation remains name/description only. R6 data shape
|
||||
expansion is active implementation, not accepted functionality.
|
||||
- R6 core/source and actual HTTP semantics pass focused Windows and full Linux
|
||||
core checks; desktop257 tests pass after independent draft/path/paging fixes.
|
||||
Native R6 acceptance and bounded scenario-value authoring remain outstanding.
|
||||
- R6 ab661f2 full suites passed Windows607/Linux610; f5467e5 desktop263 and
|
||||
strict Clippy/release passed on both platforms. Native Windows data editing,
|
||||
typed defaults, allocations, recursive qualified Call/Reply values, history and
|
||||
saved reopening passed. Source3 migration now preserves comments and nesting.
|
||||
Native found flat property browsing still ambiguous; one-record browsing with
|
||||
bounded pages now passes264 desktop tests/Clippy, pending rebuilt native checks.
|
||||
Linux native R6 acceptance remains outstanding.
|
||||
|
||||
## Assumptions and open questions
|
||||
|
||||
@@ -51,11 +55,11 @@ requires native workflows, semantic evaluators and fresh independent review.
|
||||
gestures still need their own occurrence/order semantics and task verification.
|
||||
- Routing offers a usable initial path plus manual pins; arbitrary dense diagrams
|
||||
are not guaranteed crossing-free. Measured dense full solve119ms remains a limit.
|
||||
- R3 typed historical bodies plus finite proposals appear simpler than a separate
|
||||
recursive semantic-value schema. An isolated probe supports scalar partial review
|
||||
and deleted historical references, but ordered membership/order acknowledgements
|
||||
need separate typed order checkpoints. Historical source reference parsing is
|
||||
still unimplemented; this remains a candidate awaiting independent review.
|
||||
- R3 selected design C uses finite self-tagged typed facets, separate membership
|
||||
and order acknowledgements, and transient constructor groups. Source5 historical
|
||||
references are implemented in the isolated semantic checkout. Independent review
|
||||
found narrow-acknowledgement/canonical-agreement/rollup defects; the worker has
|
||||
added regressions and fixes. Full catalog, GUI/API/spec and acceptance remain.
|
||||
|
||||
## Decisions and current strategy
|
||||
|
||||
|
||||
@@ -1,50 +1,119 @@
|
||||
# R6 data contracts — verification in progress
|
||||
# R6 data contracts — native verification in progress
|
||||
|
||||
R6 is not accepted. Main remains at state-editing acceptance a8f451e. The updated
|
||||
objective10134df9-bea2-4c02-a820-67b53d6b86f7 was read fully on2026-09-06; product
|
||||
scope is unchanged and reasoning effort must match the delegated task. The full
|
||||
first release remains incomplete. Native input is paused after physical Escape.
|
||||
R6 is not accepted. Main remains at a8f451e. The full first-release goal remains
|
||||
active and incomplete. User explicitly reauthorized native testing after Escape.
|
||||
|
||||
## Current evidence
|
||||
## Frozen production and automated evidence
|
||||
|
||||
- Core0b58107: Linux307 tests pass, one explicitly ignored benchmark; strict
|
||||
all-target core Clippy passes. Windows15 R6+28 workflows pass after final
|
||||
allocation-edge filtering. Source migration/compatibility evidence is retained.
|
||||
- Desktopb403039: Windows257 tests, strict all-target desktop Clippy and release
|
||||
build pass. Binary D:/CodexBuilds/Capella2-data-target/release/arcadia-studio.exe,
|
||||
SHA256 d4aa6ae7d36f429c0cb639cdf57e33cb8b99d158a9629c95a1510d24e406fab5.
|
||||
The later bounded scenario editor is not covered by this binary.
|
||||
- Optimized empty inheritance chains250/500/1000: Windows21.070/89.088/391.590ms;
|
||||
Linux22.381/111.662/408.129ms. These are single-run validation measurements.
|
||||
- Server41 prior tests passed. The new qualified Call/Reply workflow and all4 R6
|
||||
HTTP tests now pass with strict all-target server Clippy. Actual HTTP proves
|
||||
distinct reused/inherited/recursive field paths, preserved expression whitespace,
|
||||
phase/path422 with unchanged ETag/model/source/disk, source edits, enclosing-hop
|
||||
and terminal/base reidentification, correlation and exact restart persistence.
|
||||
Initial new-test failures were fixture misuse of untyped Port construction and
|
||||
incorrect assumption that transaction errors carry structured issues. Tests now
|
||||
use make_port and the documented command_rejected/detail plus validation endpoint.
|
||||
- Published data example was imported into actual frozen server32033FFE. Complete
|
||||
Project/StoredProject responses passed served/local OpenAPI validation; obsolete
|
||||
shapes rejected. reST strict rendering and81 OpenAPI schemas passed.
|
||||
- Independent spec review found one stale identity-only port-compatibility paragraph;
|
||||
fixed to directional explicit ancestry and strict HTML rendering passed. No other
|
||||
material R6 spec/API contradiction found in that review.
|
||||
Data integration ab661f2: Windows607 and Linux610 workspace tests pass, one explicit
|
||||
benchmark ignored each; strict workspace all-target Clippy passes on both.
|
||||
Windows261 desktop tests include the focused bounded scenario editor; Linux release
|
||||
desktop/server build passed. Logs under D:/CodexBuilds/Capella2-release1-01a06e2e:
|
||||
r6-workspace-windows-ab661f2.log and r6-workspace-windows-clippy-ab661f2.log.
|
||||
Linux logs in Capella2-data-linux-review/target/linux-verification:
|
||||
workspace-ab661f2.log, workspace-clippy-ab661f2.log, release-ab661f2.log.
|
||||
|
||||
Logs are under D:/CodexBuilds/Capella2-release1-01a06e2e:
|
||||
r6-http-paths-final.log, r6-http-all-data.log, r6-http-paths-clippy.log,
|
||||
r6-server-tests-after.log and api-r6-contract. Linux core evidence is under
|
||||
D:/CodexBuilds/Capella2-data-linux-review/target/linux-verification/report.md.
|
||||
Windows frozen executable ui-r6-windows/arcadia-studio.exe SHA256
|
||||
C3ABD9E550E1AD6824DFE273EB27A3ABB35C5C0DA97C819DCB0AB2586AF5450C.
|
||||
Current native window1835476, process session37598. No output observed; runtime.log
|
||||
has not been created by Tee-Object (do not claim an empty log file).
|
||||
|
||||
## Active checks and remaining gates
|
||||
All4 actual R6 HTTP tests pass with strict server Clippy: published data example,
|
||||
protocol/artifact identity, rejected defaults, qualified reused/inherited/recursive
|
||||
Call/Reply paths, phase/path422 with unchanged ETag/model/source/disk, source edits,
|
||||
hop/terminal/base reidentification, correlation and restart persistence. Source3
|
||||
coupled/source bundle migrations report correctly and opening alone does not write.
|
||||
Logs: r6-http-paths-final.log, r6-http-all-data.log, r6-http-paths-clippy.log.
|
||||
Initial fixture errors (untyped Port and transaction-error envelope assumption)
|
||||
were corrected before passing. Published example responses from server32033FFE
|
||||
passed served/local OpenAPI validation; obsolete shapes rejected. Strict reST HTML
|
||||
and81 OpenAPI schemas passed. One stale port compatibility paragraph was corrected.
|
||||
|
||||
The isolated Linux checkout was fast-forwarded to b403039; full workspace tests are
|
||||
running in exec98587 with its dedicated data-linux-target. Initial filesystem wait
|
||||
was verified as a live Cargo process in p9_client_rpc; it subsequently compiled.
|
||||
Do not restart from an observation timeout. Bounded scenario editor production and
|
||||
regressions are being tested by the desktop worker. Independent review found stale
|
||||
values hiding an alternative reply call; its fix is included in that worker pass.
|
||||
Optimized empty inheritance chains250/500/1000: Windows21.070/89.088/391.590ms;
|
||||
Linux22.381/111.662/408.129ms. Single-run core validation timings, not UI latency.
|
||||
|
||||
Before acceptance: integrated Windows/Linux checks, native data/association/scenario
|
||||
value workflows at normal/minimum sizes, source3 migration diagnostics, Save/reopen,
|
||||
and closure of material review findings. No R6 visual or real-app acceptance claim.
|
||||
## Personally observed Windows native workflows
|
||||
|
||||
Loaded the isolated Engineering data source fixture. Its architecture view shows
|
||||
nested fields, association role/multiplicity labels, self-reference navigation and
|
||||
selectable endpoint labels. No selection-induced dirty state observed.
|
||||
|
||||
Voltage maximum48→12 with default24 rejects when navigating; entered12 survives,
|
||||
accepted summary remains0..48/default24, and a located default error is shown.
|
||||
Repair default→12 applies together; Undo restores both old values, Redo restores
|
||||
both new values. Created Cooling water with Material/Flow and contained Mass flow
|
||||
rate Real1..1, unit kg/s, explicit default0.0. Save All wrote an included sa/types.arcadia
|
||||
file with matching typed values, leaving13objects/4links/1 expected missing-System
|
||||
warning. Navigation allocation changed Synchronous→Asynchronous; Monitoring's
|
||||
separate Asynchronous/Read allocation is preserved. Removing Monitoring allocation
|
||||
keeps Navigate; Undo restores the allocation and original checks. Followed inherited
|
||||
Latitude from Located asset to Coordinate. Saved all edits. Data layout inspected
|
||||
at1440x900 and1100x700; no overlapping controls observed.
|
||||
|
||||
Separate ui-r6-scenario-windows/model/project.arcadia was constructed with the core
|
||||
API from the saved native data, adding functional ports/exchange, correlated
|
||||
Call/Reply, reused/inherited/recursive records and30 extra fields.53objects/5links
|
||||
validate and source round-trip exactly. fixture-generator.rs retained as evidence;
|
||||
temporary project example removed. Initial generator compile/load errors were
|
||||
fixture-only and fixed using the bundle-aware loader; final build has no warnings.
|
||||
This preparation is not native scenario authoring evidence.
|
||||
|
||||
## Remaining acceptance gates
|
||||
|
||||
Native scenario focused/path/phase/draft behavior and paging; actual saved reopen;
|
||||
source3 migration diagnostics; Linux native data/scenario workflows. Closure of
|
||||
material findings before R6 acceptance. Independent semantic/correctness/spec
|
||||
reviews already drove fixes; final native observations may require further review.
|
||||
The broader release still needs semantic reconciliation, direct scenario/process
|
||||
editing, lifecycle/hosted/help work and fresh cross-disciplinary end-state review.
|
||||
|
||||
## Native findings and follow-up fixes (2026-09-06)
|
||||
|
||||
At1100x700, the53-object recursive fixture exposed32/33 nested fields in two pages.
|
||||
Native Call+Reply creation stored distinct Origin/Latitude and Destination/Latitude
|
||||
expressions despite their shared terminal UUID. One Undo removed the pair; Redo
|
||||
restored it. Save All wrote55objects/5links; source confirms both paths and reply
|
||||
correlation. Three expected checks concern the absent SA System and two unallocated
|
||||
functions. The saved evidence is ui-r6-scenario-windows/model/project.arcadia.
|
||||
|
||||
A third-hop popup exposed a material UI defect: repeated long path prefixes hid
|
||||
all terminal field names. Fix74989b6 shows the terminal name first, sorts choices,
|
||||
and retains the full address as wrapping detail text.262 desktop tests, strict
|
||||
Clippy and release build passed; native retest is pending. Intermediate fixed hash
|
||||
E592165A6FFFAEC64B67FF0A33FB4E78571527EE3C8F2CC457666DA6C277D5CB.
|
||||
|
||||
Native source3 import showed8semantic defaults,2generated allocations,1unresolved
|
||||
value address and left the original hash305F19D1B79F99F8D4CF627BA2E9CA6836BB7959CC0070227815937A699EAFEA unchanged.
|
||||
Its old desktop Save All path requested a new file and preserved the original, but
|
||||
canonical regeneration discarded comments/nesting in the upgraded copy. This is a
|
||||
material desktop/source parity defect, not a core bundle migration defect. The fix
|
||||
keeps the historical single-document adapter only for source1/2; source3+ follows
|
||||
bundle migration and propagates its report into Model checks. A regression passes
|
||||
for actual disk single-file and included-file open, no write until explicit save,
|
||||
comments, lexical ownership, report, exact saved source and clean reopened state.
|
||||
Full desktop/Clippy/build and native retest are in progress; do not accept R6 yet.
|
||||
|
||||
The old Windows native window1835476 closed normally; exec37598 exited0 with no
|
||||
runtime output beyond a newline. Re-inventory before opening the rebuilt binary.
|
||||
|
||||
## Migration retest and bounded property browsing
|
||||
|
||||
f5467e5 passed263 desktop tests, strict all-target desktop Clippy and optimized
|
||||
release on Windows/Linux. Frozen Windows SHA256
|
||||
33D1B2B6709BBC734E265568C7F93CB86A506497DEF3F4531669E5ABF8B2F039.
|
||||
Native fresh legacy.arcadia import preserved original bytes until Save All,
|
||||
displayed8defaults/2allocations/1unresolved address, and retained comments and
|
||||
nested fields in its text editor. Save All kept the same file and source4 wording;
|
||||
reopen was clean15objects/3links/4checks without a migration report. Saved SHA256
|
||||
A8C0A689FEA6CC352007ACB127DE4A45E05290830DE815385CFFBAB777255543.
|
||||
Evidence: ui-r6-final-windows/migration/legacy.arcadia.
|
||||
|
||||
The55-object recursive scenario reopened with both qualified expressions intact.
|
||||
Leaf-first labels fixed the hidden terminal names, but existing-value properties
|
||||
still flattened every representative path, causing repeated indistinguishable
|
||||
leaf names. The follow-up browses one record at a time, with24-choice pages and
|
||||
wrapping current address/location text. Up/root/page actions change only browser
|
||||
state; draft field and expression are preserved.264 desktop tests and strict
|
||||
Clippy passed, including wide-record page coverage and draft preservation across
|
||||
recursive browsing. Optimized build and native retest remain pending. Frozen
|
||||
f5467e5 window3476204 closed normally; exec93768 had no runtime output.
|
||||
|
||||
Reference in New Issue
Block a user