Merge tested R6 data workflows into direct scenario workspace

This commit is contained in:
2026-09-06 05:04:04 +03:00
8 changed files with 638 additions and 216 deletions
+115 -3
View File
@@ -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");