Merge tested R6 data workflows into direct scenario workspace
This commit is contained in:
@@ -340,6 +340,7 @@ pub enum Message {
|
|||||||
FieldShape(String, Value),
|
FieldShape(String, Value),
|
||||||
FieldAppend(String, Value),
|
FieldAppend(String, Value),
|
||||||
FieldValuePath(String, crate::data_values::FieldPathKey),
|
FieldValuePath(String, crate::data_values::FieldPathKey),
|
||||||
|
FieldValueBrowse(String, Option<crate::data_values::FieldPathKey>, usize),
|
||||||
FieldVariant(String, Value),
|
FieldVariant(String, Value),
|
||||||
FieldArray(String, Option<usize>, i32),
|
FieldArray(String, Option<usize>, i32),
|
||||||
Apply,
|
Apply,
|
||||||
@@ -1467,6 +1468,18 @@ impl App {
|
|||||||
self.status = error;
|
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) => {
|
Message::FieldValuePath(path, key) => {
|
||||||
if let Some(draft) = &mut self.draft
|
if let Some(draft) = &mut self.draft
|
||||||
&& let Err(error) = draft.value_path(&path, key)
|
&& let Err(error) = draft.value_path(&path, key)
|
||||||
@@ -2947,8 +2960,14 @@ impl App {
|
|||||||
.discovered(&disk.bundle, disk.reachable.clone());
|
.discovered(&disk.bundle, disk.reachable.clone());
|
||||||
self.show_source_file(false);
|
self.show_source_file(false);
|
||||||
self.source_diagnostics = self.document.compiled().diagnostics.clone();
|
self.source_diagnostics = self.document.compiled().diagnostics.clone();
|
||||||
self.status =
|
self.migration = self.document.compiled().decoded.migration.clone();
|
||||||
"Source project opened. Included files and comments are preserved.".into();
|
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) => {
|
Err(error) => {
|
||||||
self.canvas_document = Id::new_v4();
|
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)) =
|
&& let Some(source_files::DiskExpectation::Bytes(bytes)) =
|
||||||
disk.expectations.get(&disk.bundle.entry)
|
disk.expectations.get(&disk.bundle.entry)
|
||||||
&& let Ok(decoded) = persistence::decode_with_report_limited(bytes, LIMITS.model)
|
&& 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(
|
return Ok(LoadedSnapshot::Legacy(
|
||||||
path,
|
path,
|
||||||
@@ -3663,6 +3684,97 @@ mod source_project_tests {
|
|||||||
Ok(())
|
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) {
|
fn pending_journal(directory: &Directory, before: Option<&str>) -> (PathBuf, PathBuf) {
|
||||||
let path = directory.0.join("project.arcadia");
|
let path = directory.0.join("project.arcadia");
|
||||||
let journal = directory.0.join(".arcadia-save-project.arcadia.journal");
|
let journal = directory.0.join(".arcadia-save-project.arcadia.journal");
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ pub struct FieldPathKey {
|
|||||||
pub struct FieldPathChoice {
|
pub struct FieldPathChoice {
|
||||||
pub key: FieldPathKey,
|
pub key: FieldPathKey,
|
||||||
pub label: String,
|
pub label: String,
|
||||||
|
pub picker_label: String,
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for FieldPathChoice {
|
impl std::fmt::Display for FieldPathChoice {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
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))
|
.map(|e| format!("{} (@{})", e.name, e.alias))
|
||||||
.unwrap_or_else(|| id.to_string())
|
.unwrap_or_else(|| id.to_string())
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>();
|
||||||
.join(" → ");
|
|
||||||
let direction =
|
let direction =
|
||||||
if data::item_mechanism(project, entry.item) == Some(ExchangeMechanism::Operation) {
|
if data::item_mechanism(project, entry.item) == Some(ExchangeMechanism::Operation) {
|
||||||
match entry.direction {
|
match entry.direction {
|
||||||
@@ -63,54 +63,97 @@ fn named_choice(project: &Project, entry: data::CarriedFieldPath) -> FieldPathCh
|
|||||||
} else {
|
} 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 {
|
FieldPathChoice {
|
||||||
key: FieldPathKey {
|
key: FieldPathKey {
|
||||||
path: entry.path,
|
path: entry.path,
|
||||||
field: entry.field,
|
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(
|
pub fn choices(
|
||||||
project: &Project,
|
project: &Project,
|
||||||
exchange: &Relation,
|
exchange: &Relation,
|
||||||
phase: &MessageKind,
|
phase: &MessageKind,
|
||||||
) -> Result<Vec<FieldPathChoice>, String> {
|
) -> Result<Vec<FieldPathChoice>, String> {
|
||||||
Ok(data::try_carried_field_paths(project, exchange)?
|
Ok(sorted_choices(
|
||||||
.into_iter()
|
data::try_carried_field_paths(project, exchange)?
|
||||||
.filter(|entry| phase_allows(project, entry, phase))
|
.into_iter()
|
||||||
.map(|entry| named_choice(project, entry))
|
.filter(|entry| phase_allows(project, entry, phase))
|
||||||
.collect())
|
.map(|entry| named_choice(project, entry))
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Direct carried fields only: an unrelated deep branch must not prevent
|
/// Direct carried fields only: an unrelated deep branch must not prevent
|
||||||
/// browsing a root field. Preserve the core resolver's first carried owner.
|
/// browsing a root field. Preserve the core resolver's first carried owner.
|
||||||
pub fn roots(project: &Project, exchange: &Relation, phase: &MessageKind) -> Vec<FieldPathChoice> {
|
pub fn roots(project: &Project, exchange: &Relation, phase: &MessageKind) -> Vec<FieldPathChoice> {
|
||||||
let mut seen = std::collections::BTreeSet::new();
|
let mut seen = std::collections::BTreeSet::new();
|
||||||
exchange
|
sorted_choices(
|
||||||
.body
|
exchange
|
||||||
.items()
|
.body
|
||||||
.iter()
|
.items()
|
||||||
.flat_map(|item| {
|
.iter()
|
||||||
data::effective_fields(project, *item)
|
.flat_map(|item| {
|
||||||
.into_iter()
|
data::effective_fields(project, *item)
|
||||||
.filter_map(|field| {
|
.into_iter()
|
||||||
let SharedBody::DataField { direction, .. } = field.shared()? else {
|
.filter_map(|field| {
|
||||||
return None;
|
let SharedBody::DataField { direction, .. } = field.shared()? else {
|
||||||
};
|
return None;
|
||||||
Some(data::CarriedFieldPath {
|
};
|
||||||
item: *item,
|
Some(data::CarriedFieldPath {
|
||||||
path: vec![],
|
item: *item,
|
||||||
field: field.id,
|
path: vec![],
|
||||||
direction: *direction,
|
field: field.id,
|
||||||
|
direction: *direction,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
.filter(|entry| seen.insert(entry.field))
|
||||||
.filter(|entry| seen.insert(entry.field))
|
.filter(|entry| phase_allows(project, entry, phase))
|
||||||
.filter(|entry| phase_allows(project, entry, phase))
|
.map(|entry| named_choice(project, entry))
|
||||||
.map(|entry| named_choice(project, entry))
|
.collect(),
|
||||||
.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.
|
/// 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();
|
let mut path = key.path.clone();
|
||||||
path.push(key.field);
|
path.push(key.field);
|
||||||
Ok(data::effective_fields(project, *record)
|
Ok(sorted_choices(
|
||||||
.into_iter()
|
data::effective_fields(project, *record)
|
||||||
.map(|field| {
|
.into_iter()
|
||||||
named_choice(
|
.map(|field| {
|
||||||
project,
|
named_choice(
|
||||||
data::CarriedFieldPath {
|
project,
|
||||||
item: entry.item,
|
data::CarriedFieldPath {
|
||||||
path: path.clone(),
|
item: entry.item,
|
||||||
field: field.id,
|
path: path.clone(),
|
||||||
direction: entry.direction,
|
field: field.id,
|
||||||
},
|
direction: entry.direction,
|
||||||
)
|
},
|
||||||
})
|
)
|
||||||
.collect())
|
})
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -482,4 +527,33 @@ pub(crate) mod tests {
|
|||||||
.contains("128")
|
.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 raw: String,
|
||||||
pub editor: text_editor::Content,
|
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 struct Draft {
|
||||||
pub kind: RecordKind,
|
pub kind: RecordKind,
|
||||||
pub original: Id,
|
pub original: Id,
|
||||||
@@ -40,6 +46,7 @@ pub struct Draft {
|
|||||||
pub inputs: BTreeMap<String, Input>,
|
pub inputs: BTreeMap<String, Input>,
|
||||||
pub exact_strings: bool,
|
pub exact_strings: bool,
|
||||||
port_contract_drafts: BTreeMap<String, Value>,
|
port_contract_drafts: BTreeMap<String, Value>,
|
||||||
|
pub value_browsers: BTreeMap<String, ValueBrowser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Draft {
|
impl Draft {
|
||||||
@@ -77,11 +84,14 @@ impl Draft {
|
|||||||
inputs: BTreeMap::new(),
|
inputs: BTreeMap::new(),
|
||||||
exact_strings: false,
|
exact_strings: false,
|
||||||
port_contract_drafts: BTreeMap::new(),
|
port_contract_drafts: BTreeMap::new(),
|
||||||
|
value_browsers: BTreeMap::new(),
|
||||||
};
|
};
|
||||||
draft.rebuild();
|
draft.rebuild();
|
||||||
Some(draft)
|
Some(draft)
|
||||||
}
|
}
|
||||||
fn rebuild(&mut self) {
|
fn rebuild(&mut self) {
|
||||||
|
// Array/variant edits can change the meaning of a row path.
|
||||||
|
self.value_browsers.clear();
|
||||||
self.inputs.clear();
|
self.inputs.clear();
|
||||||
fn visit(value: &Value, path: &str, out: &mut BTreeMap<String, Input>) {
|
fn visit(value: &Value, path: &str, out: &mut BTreeMap<String, Input>) {
|
||||||
match value {
|
match value {
|
||||||
@@ -710,10 +720,15 @@ fn reference_ids(draft: &Draft, project: &Project, path: &str) -> Vec<Id> {
|
|||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} => project
|
} => project.relations.get(id).and_then(|r| {
|
||||||
.relations
|
let scope = address_path.split_last().map(|(&field, path)| {
|
||||||
.get(id)
|
crate::data_values::FieldPathKey {
|
||||||
.and_then(|r| crate::data_values::choices(project, r, message_kind).ok()),
|
path: path.to_vec(),
|
||||||
|
field,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
crate::data_values::at_scope(project, r, message_kind, scope.as_ref()).ok()
|
||||||
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
|||||||
@@ -330,97 +330,152 @@ fn message_value<'a>(
|
|||||||
} => project.relations.get(id).map(|r| (r, message_kind)),
|
} => project.relations.get(id).map(|r| (r, message_kind)),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let choices = context
|
let current_key = current
|
||||||
.map(|(r, phase)| crate::data_values::choices(project, r, phase))
|
.as_ref()
|
||||||
.unwrap_or_else(|| Ok(vec![]));
|
.map(|value| crate::data_values::FieldPathKey {
|
||||||
let mut out = column![text("Qualified carried field").size(11).color(style::MUTED)].spacing(6);
|
path: value.path.clone(),
|
||||||
match choices {
|
field: value.field,
|
||||||
Err(error) => out = out.push(text(error).size(11).color(style::MUTED)),
|
});
|
||||||
Ok(mut choices) => {
|
let selected = context.and_then(|(exchange, phase)| {
|
||||||
let current_key = current.as_ref().map(|v| crate::data_values::FieldPathKey {
|
current_key
|
||||||
path: v.path.clone(),
|
.as_ref()
|
||||||
field: v.field,
|
.and_then(|key| crate::data_values::resolve(project, exchange, phase, key))
|
||||||
});
|
});
|
||||||
let mut selected = current_key
|
let browser = draft
|
||||||
|
.value_browsers
|
||||||
|
.get(path)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| ValueBrowser {
|
||||||
|
scope: selected
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|key| choices.iter().find(|c| &c.key == key))
|
.and_then(|choice| crate::data_values::parent(&choice.key)),
|
||||||
.cloned()
|
page: 0,
|
||||||
.or_else(|| {
|
});
|
||||||
context.and_then(|(r, phase)| {
|
let mut out = column![text("Qualified carried field").size(11).color(style::MUTED)].spacing(6);
|
||||||
current_key
|
if let Some(choice) = &selected {
|
||||||
.as_ref()
|
out = out.push(text(choice.label.clone()).size(11));
|
||||||
.and_then(|key| crate::data_values::resolve(project, r, phase, key))
|
} else if let Some(key) = ¤t_key
|
||||||
})
|
&& !key.field.is_nil()
|
||||||
});
|
{
|
||||||
if let Some(choice) = &selected
|
out = out.push(
|
||||||
&& !choices.iter().any(|c| c.key == choice.key)
|
text(format!(
|
||||||
{
|
"Current address needs review: {} / {}. Choose an explicit field.",
|
||||||
choices.push(choice.clone());
|
key.path
|
||||||
}
|
.iter()
|
||||||
if selected.is_none()
|
.map(|id| project.named(*id))
|
||||||
&& let Some(key) = current_key.clone()
|
.collect::<Vec<_>>()
|
||||||
&& !key.field.is_nil()
|
.join(" → "),
|
||||||
{
|
project.named(key.field)
|
||||||
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 {
|
.size(11)
|
||||||
label: format!(
|
.color(style::MUTED),
|
||||||
"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),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let (Some((exchange, phase)), Some(current)) = (context, current) {
|
if let Some((exchange, phase)) = context {
|
||||||
let key = crate::data_values::FieldPathKey {
|
let location = browser
|
||||||
path: current.path,
|
.scope
|
||||||
field: current.field,
|
.as_ref()
|
||||||
};
|
.and_then(|key| crate::data_values::resolve(project, exchange, phase, key))
|
||||||
if crate::data_values::resolve(project, exchange, phase, &key).is_some() {
|
.map(|choice| choice.label)
|
||||||
if let Some(parent) = crate::data_values::parent(&key) {
|
.unwrap_or_else(|| "Root carried fields".into());
|
||||||
out = out.push(
|
out = out.push(
|
||||||
button(text("Up to enclosing field").size(11))
|
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)
|
.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) {
|
out = out.push(navigation);
|
||||||
Ok(children) if !children.is_empty() => {
|
}
|
||||||
let path = path.to_owned();
|
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(
|
out = out.push(
|
||||||
pick_list(
|
row![
|
||||||
children,
|
button(text("Previous").size(11))
|
||||||
None::<crate::data_values::FieldPathChoice>,
|
.style(style::nav)
|
||||||
move |choice| Message::FieldValuePath(path.clone(), choice.key),
|
.on_press_maybe((page > 0).then(|| Message::FieldValueBrowse(
|
||||||
)
|
path.into(),
|
||||||
.placeholder("Choose a field inside this record…")
|
browser.scope.clone(),
|
||||||
.text_size(12)
|
page - 1
|
||||||
.padding(8)
|
))),
|
||||||
.width(Fill),
|
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") {
|
if let Some(expression) = value.get("expression") {
|
||||||
out = out.push(super::property(
|
out = out.push(super::property(
|
||||||
@@ -435,6 +490,25 @@ fn message_value<'a>(
|
|||||||
out.into()
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -490,6 +564,25 @@ mod tests {
|
|||||||
format!("{path}/expression"),
|
format!("{path}/expression"),
|
||||||
"newly typed".into(),
|
"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(
|
let _ = app.update(Message::FieldValuePath(
|
||||||
path.into(),
|
path.into(),
|
||||||
crate::data_values::FieldPathKey {
|
crate::data_values::FieldPathKey {
|
||||||
@@ -553,6 +646,43 @@ mod tests {
|
|||||||
let _ = super::super::view(app.draft.as_ref().unwrap(), app.project());
|
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]
|
#[test]
|
||||||
fn numeric_bound_drafts_keep_partial_and_full_precision_values_out_of_accepted_state() {
|
fn numeric_bound_drafts_keep_partial_and_full_precision_values_out_of_accepted_state() {
|
||||||
let mut p = Project::empty();
|
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
|
when selection changes through Catalog or Layer outside Behavior. Reset only on
|
||||||
actual context change; preserve same-view return. Independent review reproduced
|
actual context change; preserve same-view return. Independent review reproduced
|
||||||
the leak and native Windows/Linux tests verified the correction in316dc55.
|
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.
|
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.
|
See release-data-implementation.md and release-data-contract.md in that checkout.
|
||||||
|
|
||||||
Core is committed0b58107; source/migration1230ab8. Root API/docs are integrated
|
R6 core/source/desktop are frozen at ab661f2. Full Windows607 tests and Linux610
|
||||||
on the same working tree; desktop remains in flight and R6 is not accepted.
|
tests pass (one explicit benchmark ignored on each platform); strict workspace
|
||||||
Core15 R6 +28workflow tests passed again after final allocation-arrow suppression.
|
all-target Clippy passes on both. Optimized desktop/server Linux build also passed.
|
||||||
Linux0b58107 full core307 tests passed (one explicit probe ignored by default),
|
Windows desktop261 tests include the bounded scenario value editor. Exact logs,
|
||||||
with strict all-target core Clippy. Earlier13ports/14scenarios and115 source/lib
|
binaries and runtime evidence: release-data-verification.md.
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
All4 R6 actual HTTP workflows pass, covering data protocols/artifact identity,
|
||||||
data example, protocol/artifact identity, atomic rejected defaults, query/export,
|
rejected defaults, qualified Call/Reply paths, validation locations, source edits,
|
||||||
reidentify/delete/restart, source3 bundle migration reports and old coupled3
|
reidentification, source3 migration and restart persistence. The published example's
|
||||||
envelope upgrade without write/revision. Tests exposed dropped bundle reports and
|
actual server responses passed served/local OpenAPI validation; obsolete shapes
|
||||||
rejected legitimate old source/model pairs; both root fixes passed retest.
|
reject. Strict reST rendering and81 OpenAPI schemas passed.
|
||||||
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.
|
|
||||||
|
|
||||||
Independent core review found association transition closure pulling unrelated
|
Independent core review found association transition closure pulling unrelated
|
||||||
types and missing empty-enum warning; both corrected and focused tests passed.
|
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
|
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
|
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.
|
only on actual layer/document changes; its regression failed before and passes now.
|
||||||
Root found another unresolved scale issue: scenario creation still enumerates every
|
The bounded scenario editor replaces whole-recursion enumeration and per-field
|
||||||
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.
|
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
|
Root exclusively operates native R6. The Windows13-object data model has saved
|
||||||
the dedicated Windows Cargo target. state_architecture_review independently reviews
|
native bounds/default repair, a typed physical flow/field, allocation protocol
|
||||||
R6 spec/API consistency; its data_view.rs ownership has ended. data_core runs an
|
edit, allocation removal/Undo, and inherited-owner navigation. Association endpoint
|
||||||
isolated R3 typed-baseline experiment; Linux R6 core checkout is idle and verified.
|
labels/selectability were exercised. The1100x700 data layout has been inspected.
|
||||||
Root owns API/OpenAPI/reST, docs, integration and native input. No concurrent writers.
|
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
|
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
|
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
|
2. Finish R6 core/source/desktop, integrate actual REST/schema/reST, independent
|
||||||
semantic/correctness/UX review, Windows/Linux checks and real data authoring.
|
semantic/correctness/UX review, Windows/Linux checks and real data authoring.
|
||||||
3. Implement R3 typed semantic drift/reconciliation after R6 freezes. Current
|
3. Implement R3 typed semantic drift/reconciliation after R6 freezes. Current
|
||||||
baselines/reconciliation only cover prose. Prefer historical typed-body snapshots
|
baselines/reconciliation only cover prose. Use the experimentally selected typed facet review design C; the semantic
|
||||||
and finite proposals; avoid a duplicate recursive semantic schema without evidence.
|
integration checkout records the full scope and source5 migration plan.
|
||||||
4. Complete direct scenario/process gestures, persistent coverage/filters,
|
4. Complete direct scenario/process gestures, persistent coverage/filters,
|
||||||
Home/recent/recovery, hosted desktop ETag workflows and offline guidance.
|
Home/recent/recovery, hosted desktop ETag workflows and offline guidance.
|
||||||
5. Fresh final requirements/domain/correctness/native UX/architecture review; full
|
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
|
## Environment and native ownership
|
||||||
|
|
||||||
Native input is paused after physical Escape; no R6 native trial has run.
|
The user explicitly reauthorized native testing after Escape. Root's f5467e5 R6
|
||||||
Root exclusively owns native input. Latest saved Windows trial is window1706782,
|
window3476204 and exec93768 closed normally after verified source migration and
|
||||||
ui-state-navigation-windows,49objects/28links/1 expected missing-owner warning.
|
55-object recursive scenario reopen; no runtime output. The property-browser
|
||||||
Linux navigation trial3148598 closed normally, exec46107 exit0; baseline Linux
|
replacement build is running. Original Capella is present. Older protected user7210312/6228978 were absent;
|
||||||
trial721472 also closed normally, exec72680 exit0. Independent Windows3672536 is
|
do not reset/save/close them if they return. Re-inventory before switching apps.
|
||||||
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.
|
|
||||||
|
|
||||||
Evidence: D:/CodexBuilds/Capella2-release1-01a06e2e. State source checkout/target:
|
Evidence: D:/CodexBuilds/Capella2-release1-01a06e2e. State source checkout/target:
|
||||||
D:/CodexBuilds/Capella2-state-integration and -target. Linux source/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.
|
--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
|
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.
|
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.
|
whole-model equality or flat reformatting. Independent counterexamples were fixed.
|
||||||
- R3 existing-target reconciliation remains name/description only. R6 data shape
|
- R3 existing-target reconciliation remains name/description only. R6 data shape
|
||||||
expansion is active implementation, not accepted functionality.
|
expansion is active implementation, not accepted functionality.
|
||||||
- R6 core/source and actual HTTP semantics pass focused Windows and full Linux
|
- R6 ab661f2 full suites passed Windows607/Linux610; f5467e5 desktop263 and
|
||||||
core checks; desktop257 tests pass after independent draft/path/paging fixes.
|
strict Clippy/release passed on both platforms. Native Windows data editing,
|
||||||
Native R6 acceptance and bounded scenario-value authoring remain outstanding.
|
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
|
## 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.
|
gestures still need their own occurrence/order semantics and task verification.
|
||||||
- Routing offers a usable initial path plus manual pins; arbitrary dense diagrams
|
- Routing offers a usable initial path plus manual pins; arbitrary dense diagrams
|
||||||
are not guaranteed crossing-free. Measured dense full solve119ms remains a limit.
|
are not guaranteed crossing-free. Measured dense full solve119ms remains a limit.
|
||||||
- R3 typed historical bodies plus finite proposals appear simpler than a separate
|
- R3 selected design C uses finite self-tagged typed facets, separate membership
|
||||||
recursive semantic-value schema. An isolated probe supports scalar partial review
|
and order acknowledgements, and transient constructor groups. Source5 historical
|
||||||
and deleted historical references, but ordered membership/order acknowledgements
|
references are implemented in the isolated semantic checkout. Independent review
|
||||||
need separate typed order checkpoints. Historical source reference parsing is
|
found narrow-acknowledgement/canonical-agreement/rollup defects; the worker has
|
||||||
still unimplemented; this remains a candidate awaiting independent review.
|
added regressions and fixes. Full catalog, GUI/API/spec and acceptance remain.
|
||||||
|
|
||||||
## Decisions and current strategy
|
## 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
|
R6 is not accepted. Main remains at a8f451e. The full first-release goal remains
|
||||||
objective10134df9-bea2-4c02-a820-67b53d6b86f7 was read fully on2026-09-06; product
|
active and incomplete. User explicitly reauthorized native testing after Escape.
|
||||||
scope is unchanged and reasoning effort must match the delegated task. The full
|
|
||||||
first release remains incomplete. Native input is paused after physical Escape.
|
|
||||||
|
|
||||||
## Current evidence
|
## Frozen production and automated evidence
|
||||||
|
|
||||||
- Core0b58107: Linux307 tests pass, one explicitly ignored benchmark; strict
|
Data integration ab661f2: Windows607 and Linux610 workspace tests pass, one explicit
|
||||||
all-target core Clippy passes. Windows15 R6+28 workflows pass after final
|
benchmark ignored each; strict workspace all-target Clippy passes on both.
|
||||||
allocation-edge filtering. Source migration/compatibility evidence is retained.
|
Windows261 desktop tests include the focused bounded scenario editor; Linux release
|
||||||
- Desktopb403039: Windows257 tests, strict all-target desktop Clippy and release
|
desktop/server build passed. Logs under D:/CodexBuilds/Capella2-release1-01a06e2e:
|
||||||
build pass. Binary D:/CodexBuilds/Capella2-data-target/release/arcadia-studio.exe,
|
r6-workspace-windows-ab661f2.log and r6-workspace-windows-clippy-ab661f2.log.
|
||||||
SHA256 d4aa6ae7d36f429c0cb639cdf57e33cb8b99d158a9629c95a1510d24e406fab5.
|
Linux logs in Capella2-data-linux-review/target/linux-verification:
|
||||||
The later bounded scenario editor is not covered by this binary.
|
workspace-ab661f2.log, workspace-clippy-ab661f2.log, release-ab661f2.log.
|
||||||
- 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.
|
|
||||||
|
|
||||||
Logs are under D:/CodexBuilds/Capella2-release1-01a06e2e:
|
Windows frozen executable ui-r6-windows/arcadia-studio.exe SHA256
|
||||||
r6-http-paths-final.log, r6-http-all-data.log, r6-http-paths-clippy.log,
|
C3ABD9E550E1AD6824DFE273EB27A3ABB35C5C0DA97C819DCB0AB2586AF5450C.
|
||||||
r6-server-tests-after.log and api-r6-contract. Linux core evidence is under
|
Current native window1835476, process session37598. No output observed; runtime.log
|
||||||
D:/CodexBuilds/Capella2-data-linux-review/target/linux-verification/report.md.
|
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
|
Optimized empty inheritance chains250/500/1000: Windows21.070/89.088/391.590ms;
|
||||||
running in exec98587 with its dedicated data-linux-target. Initial filesystem wait
|
Linux22.381/111.662/408.129ms. Single-run core validation timings, not UI latency.
|
||||||
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.
|
|
||||||
|
|
||||||
Before acceptance: integrated Windows/Linux checks, native data/association/scenario
|
## Personally observed Windows native workflows
|
||||||
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.
|
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