Specify R6 data contracts and verify coupled REST migration
This commit is contained in:
@@ -231,7 +231,7 @@ fn parse_source(body: &[u8]) -> ApiResult<oa_core::persistence::DecodeResult> {
|
||||
}
|
||||
|
||||
fn import_json(body: &[u8]) -> ApiResult<oa_core::persistence::DecodeResult> {
|
||||
// Format is chosen by HTTP. The shared decoder owns explicit schema-1 and schema-2 migration.
|
||||
// Format is chosen by HTTP. The shared decoder owns supported older-schema migration.
|
||||
let _: Value = json_body(body)?;
|
||||
oa_core::persistence::decode_with_report_limited(body, MODEL_LIMITS).map_err(
|
||||
|error| match error {
|
||||
@@ -525,7 +525,7 @@ async fn put_source_project(
|
||||
StatusCode::OK,
|
||||
json!({
|
||||
"revision": stored.revision, "changed": changed, "issues": diagnostics,
|
||||
"source_project": stored.source_project
|
||||
"source_project": stored.source_project, "migration": stored.migration
|
||||
}),
|
||||
))
|
||||
})
|
||||
@@ -947,14 +947,16 @@ async fn validate_candidate(
|
||||
// Advisory locations refer to submitted bytes, before Apply
|
||||
// would insert missing persistent identities.
|
||||
let diagnostics: Vec<_> = source_project::lint_bundle(&source_project, SOURCE_LIMITS).into_iter().map(source_issue).collect();
|
||||
if !diagnostics.iter().any(|issue| issue.severity == "error") {
|
||||
PreparedProject::from_bundle(source_project)?;
|
||||
}
|
||||
Ok(diagnostics)
|
||||
let migration = if !diagnostics.iter().any(|issue| issue.severity == "error") {
|
||||
PreparedProject::from_bundle(source_project)?.migration().cloned()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok((diagnostics, migration))
|
||||
});
|
||||
let diagnostics = result.unwrap_or_else(candidate_issues);
|
||||
let (diagnostics, migration) = result.unwrap_or_else(|error| (candidate_issues(error), None));
|
||||
let valid = !diagnostics.iter().any(|issue| issue.severity == "error");
|
||||
return Ok(response(stored, StatusCode::OK, json!({"revision":stored.revision,"valid":valid,"issues":diagnostics,"migration":null})));
|
||||
return Ok(response(stored, StatusCode::OK, json!({"revision":stored.revision,"valid":valid,"issues":diagnostics,"migration":migration})));
|
||||
}
|
||||
_ => return Err(ApiError::bad_request("Validation requires one matching format/payload: json with model, arcadia with source, or source-project with source_project.")),
|
||||
};
|
||||
|
||||
@@ -128,9 +128,10 @@ impl PreparedProject {
|
||||
fn from_compiled(compiled: CompiledSourceProject) -> ApiResult<Self> {
|
||||
check_model_size(&compiled.decoded.project)?;
|
||||
check_source_size(&compiled.bundle)?;
|
||||
let migration = compiled.decoded.migration.clone();
|
||||
Ok(Self {
|
||||
compiled,
|
||||
migration: None,
|
||||
migration,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -173,6 +174,10 @@ impl PreparedProject {
|
||||
&self.compiled.bundle
|
||||
}
|
||||
|
||||
pub(crate) fn migration(&self) -> Option<&MigrationReport> {
|
||||
self.migration.as_ref()
|
||||
}
|
||||
|
||||
pub(crate) fn source_issues(&self) -> Vec<crate::error::IssueDto> {
|
||||
self.compiled
|
||||
.diagnostics
|
||||
@@ -329,7 +334,12 @@ impl Store {
|
||||
let prepared = if let Some(bundle) = envelope.source_project {
|
||||
let prepared = PreparedProject::from_bundle(bundle.clone())
|
||||
.map_err(|error| corrupt(error.detail))?;
|
||||
if prepared.bundle() != &bundle || prepared.model() != &decoded.project {
|
||||
// Explicit source upgrades may change tokens and generate new
|
||||
// records. They must still agree with independently migrated
|
||||
// JSON. Current-format unstabilized/inconsistent pairs reject.
|
||||
if (prepared.bundle() != &bundle && prepared.migration.is_none())
|
||||
|| prepared.model() != &decoded.project
|
||||
{
|
||||
return Err(corrupt(
|
||||
"Stored source and model disagree, or source lacks stable identities."
|
||||
.into(),
|
||||
@@ -347,7 +357,7 @@ impl Store {
|
||||
revision: envelope.revision,
|
||||
model: decoded.project,
|
||||
source_project: prepared.compiled.bundle,
|
||||
migration: decoded.migration,
|
||||
migration: decoded.migration.or(prepared.migration),
|
||||
};
|
||||
if stored.resource_id != filename_id || stored.revision == 0 {
|
||||
return Err(corrupt(
|
||||
|
||||
@@ -8,6 +8,8 @@ use serde_json::{Value, json};
|
||||
use std::{path::Path, sync::Arc};
|
||||
use tokio::{sync::oneshot, task::JoinHandle};
|
||||
|
||||
#[path = "http/data_contracts.rs"]
|
||||
mod data_contracts;
|
||||
#[path = "http/port_anchors.rs"]
|
||||
mod port_anchors;
|
||||
#[path = "http/source_projects.rs"]
|
||||
@@ -1929,7 +1931,7 @@ async fn legacy_json_import_and_model_reidentification_keep_the_service_address(
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn schema3_migration_reports_and_invalid_typed_transaction_preserve_http_state() {
|
||||
async fn current_migration_reports_and_invalid_typed_transaction_preserve_http_state() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let old = v2_missing_ports();
|
||||
@@ -1945,7 +1947,7 @@ async fn schema3_migration_reports_and_invalid_typed_transaction_preserve_http_s
|
||||
assert_eq!(imported.status(), StatusCode::CREATED);
|
||||
let etag = imported.headers()["etag"].to_str().unwrap().to_owned();
|
||||
let summary: Value = imported.json().await.unwrap();
|
||||
assert_eq!(summary["schema_version"], 3);
|
||||
assert_eq!(summary["schema_version"], oa_core::SCHEMA_VERSION);
|
||||
assert_eq!(
|
||||
summary["migration"],
|
||||
serde_json::to_value(&expected.migration).unwrap()
|
||||
@@ -1958,7 +1960,7 @@ async fn schema3_migration_reports_and_invalid_typed_transaction_preserve_http_s
|
||||
let before = std::fs::read(&filename).unwrap();
|
||||
let envelope: Value = serde_json::from_slice(&before).unwrap();
|
||||
assert!(envelope.get("migration").is_none());
|
||||
assert_eq!(envelope["model"]["schema_version"], 3);
|
||||
assert_eq!(envelope["model"]["schema_version"], oa_core::SCHEMA_VERSION);
|
||||
let validation = server
|
||||
.client
|
||||
.post(server.url(&format!("/projects/{id}/validation")))
|
||||
@@ -2000,7 +2002,7 @@ async fn schema3_migration_reports_and_invalid_typed_transaction_preserve_http_s
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(source.starts_with("arcadia 3;"));
|
||||
assert!(source.starts_with("arcadia 4;"));
|
||||
assert_eq!(oa_core::language::parse(&source).unwrap(), stored.model);
|
||||
let no_op = server
|
||||
.client
|
||||
@@ -2049,7 +2051,7 @@ async fn reopening_v2_envelope_reports_migration_without_saving_or_advancing_rev
|
||||
let migrated = server.get(id).await;
|
||||
assert_eq!(migrated.resource_id, id);
|
||||
assert_eq!(migrated.revision, 7);
|
||||
assert_eq!(migrated.model.schema_version, 3);
|
||||
assert_eq!(migrated.model.schema_version, oa_core::SCHEMA_VERSION);
|
||||
assert_eq!(
|
||||
migrated
|
||||
.migration
|
||||
@@ -2074,7 +2076,7 @@ async fn reopening_v2_envelope_reports_migration_without_saving_or_advancing_rev
|
||||
assert_eq!(current.model.name, "Reviewed migrated model");
|
||||
let saved: Value = serde_json::from_slice(&std::fs::read(&filename).unwrap()).unwrap();
|
||||
assert_eq!(saved["revision"], 8);
|
||||
assert_eq!(saved["model"]["schema_version"], 3);
|
||||
assert_eq!(saved["model"]["schema_version"], oa_core::SCHEMA_VERSION);
|
||||
assert!(saved.get("migration").is_none());
|
||||
server.stop().await;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
//! Transport evidence for the published R6 contract, not a second model fixture.
|
||||
use super::*;
|
||||
use oa_core::source_project::{ProjectLimits, SourceBundle, compile_bundle};
|
||||
use oa_core::{DataTypeDefinition, DataValue, SharedBody, TransmissionProtocol};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn documented_data() -> Project {
|
||||
let contract = include_str!("../../../../docs/language.rst");
|
||||
let example = contract
|
||||
.split("This complete data contract example is also exercised through the REST API:")
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.split(".. code-block:: text")
|
||||
.nth(1)
|
||||
.unwrap();
|
||||
let source = example
|
||||
.lines()
|
||||
.skip_while(|line| line.trim().is_empty())
|
||||
.take_while(|line| line.starts_with(" ") || line.is_empty())
|
||||
.map(|line| line.strip_prefix(" ").unwrap_or(line))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let model = oa_core::language::parse(&source).unwrap();
|
||||
oa_core::validate_candidate(&model).unwrap();
|
||||
model
|
||||
}
|
||||
fn id(model: &Project, alias: &str) -> Id {
|
||||
model
|
||||
.identities()
|
||||
.into_iter()
|
||||
.find(|(_, a)| *a == alias)
|
||||
.unwrap()
|
||||
.0
|
||||
}
|
||||
fn assert_pair(stored: &StoredProject) {
|
||||
let compiled = compile_bundle(&stored.source_project, ProjectLimits::default()).unwrap();
|
||||
assert_eq!(compiled.decoded.project, stored.model);
|
||||
assert_eq!(compiled.bundle, stored.source_project);
|
||||
}
|
||||
async fn commands(
|
||||
server: &TestServer,
|
||||
current: &StoredProject,
|
||||
commands: Vec<Command>,
|
||||
) -> reqwest::Response {
|
||||
server
|
||||
.client
|
||||
.post(server.url(&format!("/projects/{}/transactions", current.resource_id)))
|
||||
.header("if-match", current.etag())
|
||||
.json(&json!({"commands":commands}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn published_data_contract_queries_atomic_edits_identity_and_restart() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let model = documented_data();
|
||||
let (resource, _) = server.import(&model).await;
|
||||
let before = server.get(resource).await;
|
||||
assert_eq!(before.model, model);
|
||||
assert_pair(&before);
|
||||
for (kind, count) in [("InterfaceItemAllocation", 2), ("DataAssociation", 1)] {
|
||||
let result: Value = server
|
||||
.client
|
||||
.get(server.url(&format!("/projects/{resource}/relations?kind={kind}")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.error_for_status()
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result["items"].as_array().unwrap().len(), count);
|
||||
}
|
||||
let voltage = id(&model, "voltage");
|
||||
let mut invalid = model.elements[&voltage].clone();
|
||||
let Some(SharedBody::DataType {
|
||||
definition: DataTypeDefinition::Real { maximum, .. },
|
||||
..
|
||||
}) = invalid.shared_mut()
|
||||
else {
|
||||
panic!()
|
||||
};
|
||||
*maximum = Some(12.0); // Existing default24V is outside this bound.
|
||||
let filename = directory.path().join(format!("{resource}.json"));
|
||||
let disk_before = std::fs::read(&filename).unwrap();
|
||||
assert_eq!(
|
||||
commands(
|
||||
&server,
|
||||
&before,
|
||||
vec![Command::EditElement(voltage, invalid.clone())]
|
||||
)
|
||||
.await
|
||||
.status(),
|
||||
StatusCode::UNPROCESSABLE_ENTITY
|
||||
);
|
||||
assert_eq!(server.get(resource).await.etag(), before.etag());
|
||||
assert_eq!(std::fs::read(&filename).unwrap(), disk_before);
|
||||
|
||||
let Some(SharedBody::DataType { default, .. }) = invalid.shared_mut() else {
|
||||
panic!()
|
||||
};
|
||||
*default = Some(DataValue::Real(12.0));
|
||||
let nav = id(&model, "nav_operation");
|
||||
let other = id(&model, "monitor_operation");
|
||||
let mut allocation = model.relations[&nav].clone();
|
||||
let oa_core::RelationBody::InterfaceItemAllocation { transmission, .. } = &mut allocation.body
|
||||
else {
|
||||
panic!()
|
||||
};
|
||||
*transmission = TransmissionProtocol::Unicast;
|
||||
let artifact = oa_core::ArtifactLink {
|
||||
id: Id::new_v4(),
|
||||
alias: "navigation_evidence".into(),
|
||||
name: "Navigation CAD evidence".into(),
|
||||
description: "Independent allocation evidence".into(),
|
||||
owner: nav,
|
||||
relation: oa_core::ArtifactRelation::Verifies,
|
||||
uri: "cad://navigation/connector".into(),
|
||||
revision: Some("review-17".into()),
|
||||
fragment: Some("pin-3".into()),
|
||||
};
|
||||
let response = commands(
|
||||
&server,
|
||||
&before,
|
||||
vec![
|
||||
Command::EditElement(voltage, invalid),
|
||||
Command::EditRelation(nav, allocation.clone()),
|
||||
Command::CreateArtifact(artifact.clone()),
|
||||
],
|
||||
)
|
||||
.await;
|
||||
assert_eq!(
|
||||
response.status(),
|
||||
StatusCode::OK,
|
||||
"{}",
|
||||
response.text().await.unwrap()
|
||||
);
|
||||
let changed = server.get(resource).await;
|
||||
assert_eq!(changed.revision, before.revision + 1);
|
||||
assert_eq!(changed.model.relations[&other], model.relations[&other]);
|
||||
assert_eq!(changed.model.relations[&nav], allocation);
|
||||
assert_eq!(changed.model.artifact_links[&artifact.id], artifact);
|
||||
assert_pair(&changed);
|
||||
assert_eq!(
|
||||
commands(&server, &before, vec![Command::Rename(nav, "Stale".into())])
|
||||
.await
|
||||
.status(),
|
||||
StatusCode::PRECONDITION_FAILED
|
||||
);
|
||||
|
||||
let renamed = Id::new_v4();
|
||||
assert_eq!(
|
||||
commands(&server, &changed, vec![Command::Reidentify(nav, renamed)])
|
||||
.await
|
||||
.status(),
|
||||
StatusCode::OK
|
||||
);
|
||||
let reidentified = server.get(resource).await;
|
||||
assert_eq!(
|
||||
reidentified.model.artifact_links[&artifact.id].owner,
|
||||
renamed
|
||||
);
|
||||
// This allocation is not enforcing a live boundary, so removal is valid.
|
||||
assert_eq!(
|
||||
commands(&server, &reidentified, vec![Command::Delete(renamed)])
|
||||
.await
|
||||
.status(),
|
||||
StatusCode::OK
|
||||
);
|
||||
let removed = server.get(resource).await;
|
||||
assert!(removed.model.elements.contains_key(&id(&model, "navigate")));
|
||||
assert_eq!(removed.model.relations[&other], model.relations[&other]);
|
||||
assert!(!removed.model.artifact_links.contains_key(&artifact.id));
|
||||
assert_pair(&removed);
|
||||
let source = server
|
||||
.client
|
||||
.get(server.url(&format!("/projects/{resource}/source")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(source.starts_with("arcadia 4;"));
|
||||
assert_eq!(oa_core::language::parse(&source).unwrap(), removed.model);
|
||||
server.stop().await;
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let reopened = server.get(resource).await;
|
||||
assert_eq!(reopened.model, removed.model);
|
||||
assert_eq!(reopened.etag(), removed.etag());
|
||||
assert_pair(&reopened);
|
||||
server.stop().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn authored_schema3_bundle_upgrade_reports_data_defaults_and_preserves_files() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let old = SourceBundle {
|
||||
entry: "legacy.arcadia".into(), files: BTreeMap::from([
|
||||
("legacy.arcadia".into(), "// Entry rationale\narcadia 3; project old_data \"Old data\" { include \"dictionary.arcadia\"; }\n".into()),
|
||||
("dictionary.arcadia".into(), "// Event rationale\nsa_exchange_item notification \"Notification\" { kind Event; }\n// Interface rationale\nsa_interface contract \"Contract\" { items [@notification]; }\n".into())
|
||||
])
|
||||
};
|
||||
let response = server
|
||||
.client
|
||||
.post(server.url("/projects/import-source-project"))
|
||||
.json(&old)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
let summary: Value = response.json().await.unwrap();
|
||||
let resource = summary["resource_id"].as_str().unwrap().parse().unwrap();
|
||||
let stored = server.get(resource).await;
|
||||
let report = stored.migration.as_ref().unwrap();
|
||||
assert_eq!((report.from_schema, report.to_schema), (3, 4));
|
||||
assert_eq!(report.generated_interface_allocations.len(), 1);
|
||||
assert!(!report.semantic_defaults.is_empty());
|
||||
let validated: Value = server
|
||||
.client
|
||||
.post(server.url(&format!("/projects/{resource}/validation")))
|
||||
.json(&json!({"format":"source-project","source_project":old}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.json()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(validated["valid"], true);
|
||||
assert_eq!(validated["migration"]["from_schema"], 3);
|
||||
assert_eq!(
|
||||
validated["migration"]["generated_interface_allocations"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(stored.source_project.files.len(), 2);
|
||||
assert!(stored.source_project.files["legacy.arcadia"].contains("arcadia 4;"));
|
||||
for text in [
|
||||
"// Event rationale",
|
||||
"// Interface rationale",
|
||||
"interface_item_allocation",
|
||||
] {
|
||||
assert!(stored.source_project.files["dictionary.arcadia"].contains(text));
|
||||
}
|
||||
assert_pair(&stored);
|
||||
let filename = directory.path().join(format!("{resource}.json"));
|
||||
let bytes = std::fs::read(&filename).unwrap();
|
||||
server.stop().await;
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let reopened = server.get(resource).await;
|
||||
assert_eq!(reopened.model, stored.model);
|
||||
assert_eq!(reopened.source_project, stored.source_project);
|
||||
assert!(reopened.migration.is_none());
|
||||
assert_eq!(std::fs::read(filename).unwrap(), bytes);
|
||||
server.stop().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn existing_schema3_coupled_envelope_upgrades_in_memory_until_explicit_save() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let resource = Id::new_v4();
|
||||
let filename = directory.path().join(format!("{resource}.json"));
|
||||
let old_model: Value = serde_json::from_str(include_str!(
|
||||
"../../../oa-core/tests/fixtures/v3-data-contract.json"
|
||||
))
|
||||
.unwrap();
|
||||
let old_bundle = SourceBundle {
|
||||
entry: "project.arcadia".into(),
|
||||
files: BTreeMap::from([(
|
||||
"project.arcadia".into(),
|
||||
include_str!("../../../oa-core/tests/fixtures/v3-data-contract.arcadia").into(),
|
||||
)]),
|
||||
};
|
||||
let original = serde_json::to_vec(&json!({"resource_id":resource,"revision":17,"model":old_model,"source_project":old_bundle})).unwrap();
|
||||
std::fs::write(&filename, &original).unwrap();
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let opened = server.get(resource).await;
|
||||
assert_eq!(opened.revision, 17);
|
||||
assert_eq!(opened.model.schema_version, 4);
|
||||
assert_eq!(opened.migration.as_ref().unwrap().from_schema, 3);
|
||||
assert!(opened.source_project.files["project.arcadia"].contains("arcadia 4;"));
|
||||
assert_pair(&opened);
|
||||
assert_eq!(std::fs::read(&filename).unwrap(), original);
|
||||
assert_eq!(
|
||||
commands(
|
||||
&server,
|
||||
&opened,
|
||||
vec![Command::Rename(
|
||||
opened.model.id,
|
||||
"Reviewed data migration".into()
|
||||
)]
|
||||
)
|
||||
.await
|
||||
.status(),
|
||||
StatusCode::OK
|
||||
);
|
||||
let saved = server.get(resource).await;
|
||||
assert_eq!(saved.revision, 18);
|
||||
let bytes = std::fs::read(&filename).unwrap();
|
||||
assert_ne!(bytes, original);
|
||||
server.stop().await;
|
||||
let server = TestServer::start(directory.path(), None).await;
|
||||
let reopened = server.get(resource).await;
|
||||
assert_eq!(reopened.model, saved.model);
|
||||
assert_eq!(reopened.source_project, saved.source_project);
|
||||
assert_eq!(reopened.etag(), saved.etag());
|
||||
assert!(reopened.migration.is_none());
|
||||
assert_eq!(std::fs::read(&filename).unwrap(), bytes);
|
||||
server.stop().await;
|
||||
}
|
||||
@@ -6,10 +6,10 @@ fn authored() -> SourceBundle {
|
||||
let bundle = SourceBundle {
|
||||
entry: "harbor.arcadia".into(),
|
||||
files: BTreeMap::from([
|
||||
("harbor.arcadia".into(), "// Harbor engineering rationale 航海\r\narcadia 3; project harbor \"Harbor rescue\" {\r\n include \"team/first.arcadia\";\r\n include \"team/second.arcadia\";\r\n include \"contracts.arcadia\";\r\n include \"work.arcadia\";\r\n}\r\n".into()),
|
||||
("harbor.arcadia".into(), "// Harbor engineering rationale 航海\r\narcadia 4; project harbor \"Harbor rescue\" {\r\n include \"team/first.arcadia\";\r\n include \"team/second.arcadia\";\r\n include \"contracts.arcadia\";\r\n include \"work.arcadia\";\r\n}\r\n".into()),
|
||||
("team/first.arcadia".into(), "// First payload rationale\r\nsa_exchange_item first \"First payload\" { description \"Reviewed first\"; }\r\n".into()),
|
||||
("team/second.arcadia".into(), "// Second payload rationale\r\nsa_exchange_item second \"Second payload\" {}\r\n".into()),
|
||||
("contracts.arcadia".into(), "// Contract ownership stays here\r\nsa_interface contract \"Contract\" { items [\r\n @first // first reference rationale\r\n ,\r\n @second // second reference rationale\r\n ]; }\r\n".into()),
|
||||
("contracts.arcadia".into(), "// Contract ownership stays here\r\nsa_interface contract \"Contract\" {}\r\ninterface_item_allocation first_allocation \"First allocation\" { source @contract; target @first // first reference rationale\r\n; order 0; }\r\ninterface_item_allocation second_allocation \"Second allocation\" { source @contract; target @second // second reference rationale\r\n; order 1; }\r\n".into()),
|
||||
("work.arcadia".into(), "// Operational rationale\r\noa_activity assess \"Assess assistance\" {}\r\n".into()),
|
||||
]),
|
||||
};
|
||||
|
||||
+32
-8
@@ -784,8 +784,8 @@ candidate validation reports the same diagnostic in its 200 response.
|
||||
Parsing, validation and query processing use snapshot workers, so this work
|
||||
does not hold the catalog lock or serialize unrelated model preparation.</p>
|
||||
<p>Import accepts schema-1 JSON through the shared explicit migration adapter,
|
||||
as well as schema-2 native JSON. Source import uses the shared language parser
|
||||
and its supported migrations. Export uses schema 3 / arcadia 3. Native JSON
|
||||
as well as schema-2, schema-3 and current schema-4 JSON. Source import uses the shared language parser
|
||||
and its supported migrations. Export uses schema 4 / arcadia 4. Native JSON
|
||||
replacement accepts supported older schemas through the same explicit migration.
|
||||
Only documented query parameters are accepted. In particular, appending
|
||||
<span class="docutils literal"><span class="pre">?revision=...</span></span> to model/source export is an error, not historical retrieval.</p>
|
||||
@@ -796,7 +796,7 @@ Only documented query parameters are accepted. In particular, appending
|
||||
<pre class="literal-block">{
|
||||
"entry": "rescue.arcadia",
|
||||
"files": {
|
||||
"rescue.arcadia": "arcadia 3; project rescue \"Rescue\" { include \"oa/work.arcadia\"; }\n",
|
||||
"rescue.arcadia": "arcadia 4; project rescue \"Rescue\" { include \"oa/work.arcadia\"; }\n",
|
||||
"oa/work.arcadia": "// Engineering rationale\noa_activity assess \"Assess assistance\" {}\n"
|
||||
}
|
||||
}</pre>
|
||||
@@ -807,8 +807,9 @@ targets or another hosted resource. All submitted files must be reachable;
|
||||
missing files, cycles, duplicate keys, case collisions and escaping paths are
|
||||
rejected. The bundle permits at most 256 files, 32 include edges along a path,
|
||||
and 1,024 include edges in total. Model and source-byte budgets apply across
|
||||
the complete bundle, not separately per file. Bundle syntax is source3;
|
||||
single-file legacy migration remains available through interchange import.</p>
|
||||
the complete bundle, not separately per file. Current bundle syntax is source4; source3 bundles migrate explicitly while
|
||||
preserving their files/includes/comments. V1/V2 single-file migration remains
|
||||
available through interchange import.</p>
|
||||
<p>Compilation inserts UUIDs into headers that omit them. Import returns 201 with
|
||||
Location/ETag; GET source-project retrieves the stabilized accepted bundle.
|
||||
PUT returns <span class="docutils literal">revision</span>, <span class="docutils literal">changed</span>, located <span class="docutils literal">issues</span> and that accepted
|
||||
@@ -965,8 +966,11 @@ does not execute conditions or simulate a process.</p>
|
||||
store <span class="docutils literal">message_kind</span>, optional correlated-call <span class="docutils literal">reply_to</span> and contextual
|
||||
<span class="docutils literal">values</span>. Message kinds are Asynchronous, Call, Reply, Create, Delete, or
|
||||
<span class="docutils literal"><span class="pre">{"Timer":{"expression":"after</span> 5 <span class="pre">s"}}</span></span>. Each value record contains a
|
||||
carried DataField UUID in <span class="docutils literal">field</span> and its textual <span class="docutils literal">expression</span>; expressions
|
||||
do not change the shared exchange item's type or evaluate server-side.</p>
|
||||
carried DataField UUID in <span class="docutils literal">field</span>, enclosing field UUID list <span class="docutils literal">path</span> (default
|
||||
[]) and textual <span class="docutils literal">expression</span>. Identity is (path, field), allowing repeated uses
|
||||
of a Record. Operation Call/Reply direction checks use the direct parameter;
|
||||
Reference storage stops nested payload traversal. Expressions do not change the
|
||||
shared exchange item's type or evaluate server-side.</p>
|
||||
<p><span class="docutils literal">ScenarioUse</span> contains a referenced <span class="docutils literal">scenario</span> and one-to-one lifeline
|
||||
<span class="docutils literal">bindings</span> records with <span class="docutils literal">referenced</span> and <span class="docutils literal">local</span> UUIDs. The core validates
|
||||
viewpoint/layer compatibility, call/reply order and reversal, lifetime order,
|
||||
@@ -978,6 +982,26 @@ exports make those compatibility defaults explicit. This preserves original V2
|
||||
models while the release schema is being integrated; it does not silently
|
||||
reinterpret old mixed lifelines as a strict new viewpoint.</p>
|
||||
</section>
|
||||
<section id="data-and-interface-contracts">
|
||||
<h2>Data and interface contracts</h2>
|
||||
<p>Schema4 uses typed bounded DataTypeDefinition and DataValue constructors, field
|
||||
storage/defaults/directions, and single specialization. Exact JSON shapes are in
|
||||
<span class="docutils literal">openapi.json</span> and semantic rules and runnable source in <span class="docutils literal">language.rst</span> section 4.5.
|
||||
Interface membership is an identified InterfaceItemAllocation relation with
|
||||
independent order/transmission/acquisition. DataAssociation relates Record types
|
||||
with named, navigable, multiplicity-bearing ends; it does not add carried fields.</p>
|
||||
<p>Use ordinary relation queries, transactions and artifact links, for example
|
||||
<span class="docutils literal">GET <span class="pre">/api/v1/projects/{id}/relations?kind=InterfaceItemAllocation</span></span>. The service
|
||||
and desktop use the same inheritance/path/default validation. Invalid bounds,
|
||||
defaults, directions, cycles or contract-breaking deletions reject atomically,
|
||||
preserving the accepted source/model, revision and stored bytes. Correct a related
|
||||
contract in the same transaction when removing a used interface allocation.</p>
|
||||
<p>Explicit schema1/2/3 migration preserves prior identities and typed ports. Reports
|
||||
add semantic defaults, generated interface allocations and unresolved message
|
||||
values. Old source3 bundles retain files/includes/comments during upgrade; all
|
||||
current exports use schema4/source4. Reading an old envelope does not write it or
|
||||
advance its ETag. Canonical exports omit transient migration reports.</p>
|
||||
</section>
|
||||
<section id="validation">
|
||||
<h2>Validation</h2>
|
||||
<p>GET returns current-model diagnostics. POST accepts either:</p>
|
||||
@@ -985,7 +1009,7 @@ reinterpret old mixed lifelines as a strict new viewpoint.</p>
|
||||
<p>or:</p>
|
||||
<pre class="literal-block">{"format":"arcadia", "source":"complete source document"}</pre>
|
||||
<p>or:</p>
|
||||
<pre class="literal-block">{"format":"source-project", "source_project":{"entry":"rescue.arcadia", "files":{"rescue.arcadia":"arcadia 3; project rescue \"Rescue\" {}"}}}</pre>
|
||||
<pre class="literal-block">{"format":"source-project", "source_project":{"entry":"rescue.arcadia", "files":{"rescue.arcadia":"arcadia 4; project rescue \"Rescue\" {}"}}}</pre>
|
||||
<p>A well-formed validation request returns 200 with <span class="docutils literal">valid</span> and <span class="docutils literal">issues</span> even
|
||||
if its candidate is invalid, including a model record that fails typed decoding.
|
||||
Malformed request JSON or an invalid format/payload envelope is a 400.
|
||||
|
||||
+35
-8
@@ -146,8 +146,8 @@ Parsing, validation and query processing use snapshot workers, so this work
|
||||
does not hold the catalog lock or serialize unrelated model preparation.
|
||||
|
||||
Import accepts schema-1 JSON through the shared explicit migration adapter,
|
||||
as well as schema-2 native JSON. Source import uses the shared language parser
|
||||
and its supported migrations. Export uses schema 3 / arcadia 3. Native JSON
|
||||
as well as schema-2, schema-3 and current schema-4 JSON. Source import uses the shared language parser
|
||||
and its supported migrations. Export uses schema 4 / arcadia 4. Native JSON
|
||||
replacement accepts supported older schemas through the same explicit migration.
|
||||
Only documented query parameters are accepted. In particular, appending
|
||||
``?revision=...`` to model/source export is an error, not historical retrieval.
|
||||
@@ -160,7 +160,7 @@ A source bundle contains ``entry`` and a map of ``files``. For example::
|
||||
{
|
||||
"entry": "rescue.arcadia",
|
||||
"files": {
|
||||
"rescue.arcadia": "arcadia 3; project rescue \"Rescue\" { include \"oa/work.arcadia\"; }\n",
|
||||
"rescue.arcadia": "arcadia 4; project rescue \"Rescue\" { include \"oa/work.arcadia\"; }\n",
|
||||
"oa/work.arcadia": "// Engineering rationale\noa_activity assess \"Assess assistance\" {}\n"
|
||||
}
|
||||
}
|
||||
@@ -172,8 +172,9 @@ targets or another hosted resource. All submitted files must be reachable;
|
||||
missing files, cycles, duplicate keys, case collisions and escaping paths are
|
||||
rejected. The bundle permits at most 256 files, 32 include edges along a path,
|
||||
and 1,024 include edges in total. Model and source-byte budgets apply across
|
||||
the complete bundle, not separately per file. Bundle syntax is source3;
|
||||
single-file legacy migration remains available through interchange import.
|
||||
the complete bundle, not separately per file. Current bundle syntax is source4; source3 bundles migrate explicitly while
|
||||
preserving their files/includes/comments. V1/V2 single-file migration remains
|
||||
available through interchange import.
|
||||
|
||||
Compilation inserts UUIDs into headers that omit them. Import returns 201 with
|
||||
Location/ETag; GET source-project retrieves the stabilized accepted bundle.
|
||||
@@ -355,8 +356,11 @@ Scenario bodies store an explicit ``viewpoint``. Occurrence Exchange bodies
|
||||
store ``message_kind``, optional correlated-call ``reply_to`` and contextual
|
||||
``values``. Message kinds are Asynchronous, Call, Reply, Create, Delete, or
|
||||
``{"Timer":{"expression":"after 5 s"}}``. Each value record contains a
|
||||
carried DataField UUID in ``field`` and its textual ``expression``; expressions
|
||||
do not change the shared exchange item's type or evaluate server-side.
|
||||
carried DataField UUID in ``field``, enclosing field UUID list ``path`` (default
|
||||
[]) and textual ``expression``. Identity is (path, field), allowing repeated uses
|
||||
of a Record. Operation Call/Reply direction checks use the direct parameter;
|
||||
Reference storage stops nested payload traversal. Expressions do not change the
|
||||
shared exchange item's type or evaluate server-side.
|
||||
|
||||
``ScenarioUse`` contains a referenced ``scenario`` and one-to-one lifeline
|
||||
``bindings`` records with ``referenced`` and ``local`` UUIDs. The core validates
|
||||
@@ -370,6 +374,29 @@ exports make those compatibility defaults explicit. This preserves original V2
|
||||
models while the release schema is being integrated; it does not silently
|
||||
reinterpret old mixed lifelines as a strict new viewpoint.
|
||||
|
||||
Data and interface contracts
|
||||
----------------------------
|
||||
|
||||
Schema4 uses typed bounded DataTypeDefinition and DataValue constructors, field
|
||||
storage/defaults/directions, and single specialization. Exact JSON shapes are in
|
||||
``openapi.json`` and semantic rules and runnable source in ``language.rst`` section 4.5.
|
||||
Interface membership is an identified InterfaceItemAllocation relation with
|
||||
independent order/transmission/acquisition. DataAssociation relates Record types
|
||||
with named, navigable, multiplicity-bearing ends; it does not add carried fields.
|
||||
|
||||
Use ordinary relation queries, transactions and artifact links, for example
|
||||
``GET /api/v1/projects/{id}/relations?kind=InterfaceItemAllocation``. The service
|
||||
and desktop use the same inheritance/path/default validation. Invalid bounds,
|
||||
defaults, directions, cycles or contract-breaking deletions reject atomically,
|
||||
preserving the accepted source/model, revision and stored bytes. Correct a related
|
||||
contract in the same transaction when removing a used interface allocation.
|
||||
|
||||
Explicit schema1/2/3 migration preserves prior identities and typed ports. Reports
|
||||
add semantic defaults, generated interface allocations and unresolved message
|
||||
values. Old source3 bundles retain files/includes/comments during upgrade; all
|
||||
current exports use schema4/source4. Reading an old envelope does not write it or
|
||||
advance its ETag. Canonical exports omit transient migration reports.
|
||||
|
||||
Validation
|
||||
----------
|
||||
|
||||
@@ -383,7 +410,7 @@ or::
|
||||
|
||||
or::
|
||||
|
||||
{"format":"source-project", "source_project":{"entry":"rescue.arcadia", "files":{"rescue.arcadia":"arcadia 3; project rescue \"Rescue\" {}"}}}
|
||||
{"format":"source-project", "source_project":{"entry":"rescue.arcadia", "files":{"rescue.arcadia":"arcadia 4; project rescue \"Rescue\" {}"}}}
|
||||
|
||||
A well-formed validation request returns 200 with ``valid`` and ``issues`` even
|
||||
if its candidate is invalid, including a model record that fails typed decoding.
|
||||
|
||||
+215
-42
@@ -623,7 +623,7 @@ a { text-decoration: none; }
|
||||
<h1 class="title">Arcadia Studio OA / SA Language and Editing Contract</h1>
|
||||
<dl class="docinfo simple">
|
||||
<dt class="version">Version<span class="colon">:</span></dt>
|
||||
<dd class="version">3</dd>
|
||||
<dd class="version">4</dd>
|
||||
<dt class="status">Status<span class="colon">:</span></dt>
|
||||
<dd class="status">Normative current implementation contract; first-release integration</dd>
|
||||
<dt class="core-implementation">Core implementation<span class="colon">:</span></dt>
|
||||
@@ -637,14 +637,13 @@ a { text-decoration: none; }
|
||||
<h2>1. Scope and conformance</h2>
|
||||
<p>This specification defines the shared Operational Analysis (OA) and System
|
||||
Analysis (SA) model, its textual language, graphical editing obligations,
|
||||
validation, persistence, and explicit migration from versions 1 and 2. MUST, MUST NOT,
|
||||
validation, persistence, and explicit migration from versions 1, 2 and 3. MUST, MUST NOT,
|
||||
and MAY indicate requirements, prohibitions, and permitted choices.</p>
|
||||
<p>Schema 3 introduces typed function and component ports, required functional
|
||||
exchange endpoints, independently oriented boundary exchanges, and explicit
|
||||
PortAllocation relations. First-release scenario/state additions remain in
|
||||
scope; this schema change does not declare native acceptance or the wider
|
||||
release complete. The preserved schema-2 reader validates the original
|
||||
contract before migration.</p>
|
||||
<p>Schema 4 adds bounded reusable data types, typed scalar defaults, exchange
|
||||
mechanisms, qualified message values, specialization, identified interface
|
||||
allocations and reference associations. It retains schema 3 typed ports and
|
||||
state views. Explicit older readers preserve existing meanings and identities.
|
||||
This contract does not by itself establish native acceptance or release completion.</p>
|
||||
<p>OA describes stakeholders, operational work and needs. SA describes the
|
||||
selected system boundary, external actors, functions, services and expected
|
||||
behavior. SA permits at most one System of Interest; its absence is an
|
||||
@@ -662,7 +661,7 @@ Actual verification evidence is separate from this contract.</p>
|
||||
</section>
|
||||
<section id="one-authoritative-model">
|
||||
<h2>2. One authoritative model</h2>
|
||||
<p>A Project stores <span class="docutils literal">schema_version</span> (3), <span class="docutils literal">id</span>, <span class="docutils literal">alias</span>, <span class="docutils literal">name</span>,
|
||||
<p>A Project stores <span class="docutils literal">schema_version</span> (4), <span class="docutils literal">id</span>, <span class="docutils literal">alias</span>, <span class="docutils literal">name</span>,
|
||||
<span class="docutils literal">description</span>, and maps named <span class="docutils literal">elements</span>, <span class="docutils literal">relations</span>, <span class="docutils literal">diagrams</span>,
|
||||
<span class="docutils literal">artifact_links</span>, and <span class="docutils literal">traces</span>. Each map is keyed by the UUID contained in
|
||||
its record. Duplicate map keys and mismatching keys/identities are errors.</p>
|
||||
@@ -722,20 +721,20 @@ lists all additional fields. <span class="docutils literal">ref</span> means <sp
|
||||
<td><p><span class="docutils literal">[]</span></p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_exchange_item</span>, <span class="docutils literal">sa_exchange_item</span></p></td>
|
||||
<td><p><span class="docutils literal">kind</span>: Information, Material, Energy, Event</p></td>
|
||||
<td><p>Information</p></td>
|
||||
<td><p><span class="docutils literal">kind</span>: Information, Material, Energy; <span class="docutils literal">mechanism</span>: ExchangeMechanism; <span class="docutils literal">supertype</span>: item ref?</p></td>
|
||||
<td><p>Information; Unspecified; none</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_data_type</span>, <span class="docutils literal">sa_data_type</span></p></td>
|
||||
<td><p><span class="docutils literal">definition</span>: Boolean, Integer, Real, String, Record, or Enumeration constructor</p></td>
|
||||
<td><p>String</p></td>
|
||||
<td><p><span class="docutils literal">definition</span>: DataTypeDefinition; <span class="docutils literal">default</span>: DataValue?; <span class="docutils literal">unit</span>: string</p></td>
|
||||
<td><p>String with minimum_length 0 / maximum_length none; none; <span class="docutils literal">""</span></p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_data_field</span>, <span class="docutils literal">sa_data_field</span></p></td>
|
||||
<td><p><span class="docutils literal">type_ref</span>; <span class="docutils literal">minimum</span>: u32; <span class="docutils literal">maximum</span>: optional u32; <span class="docutils literal">unit</span>: string</p></td>
|
||||
<td><p>String; 1; 1; <span class="docutils literal">""</span></p></td>
|
||||
<td><p><span class="docutils literal">type_ref</span>; <span class="docutils literal">minimum</span>: u32; <span class="docutils literal">maximum</span>: optional u32; <span class="docutils literal">unit</span>: string; <span class="docutils literal">direction</span>: ParameterDirection; <span class="docutils literal">storage</span>: FieldStorage; <span class="docutils literal">default</span>: DataValue list?</p></td>
|
||||
<td><p>String; 1; 1; <span class="docutils literal">""</span>; Unspecified; Value; none</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_interface</span>, <span class="docutils literal">sa_interface</span></p></td>
|
||||
<td><p><span class="docutils literal">items</span>: exchange-item refs</p></td>
|
||||
<td><p><span class="docutils literal">[]</span></p></td>
|
||||
<td><p><span class="docutils literal">supertype</span>: interface ref?</p></td>
|
||||
<td><p>none; membership is an identified interface_item_allocation relation</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">oa_port</span>, <span class="docutils literal">sa_port</span></p></td>
|
||||
<td><p><span class="docutils literal">contract</span>: required PortContract; <span class="docutils literal">legacy</span>: optional LegacyPortContract</p></td>
|
||||
@@ -883,6 +882,14 @@ references. Their kind is the declaration keyword:</p>
|
||||
<td><p>Same-layer participant → leaf activity/function</p></td>
|
||||
<td><p>None</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">interface_item_allocation</span></p></td>
|
||||
<td><p>Same-layer Interface → ExchangeItem</p></td>
|
||||
<td><p><span class="docutils literal">order</span> u32 / 0; <span class="docutils literal">transmission</span> TransmissionProtocol / Unspecified; <span class="docutils literal">acquisition</span> AcquisitionProtocol / Unspecified</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">data_association</span></p></td>
|
||||
<td><p>Same-layer Record DataType → Record DataType</p></td>
|
||||
<td><p><span class="docutils literal">source_role</span>, <span class="docutils literal">target_role</span> / ""; <span class="docutils literal">source_minimum</span>, <span class="docutils literal">target_minimum</span> / 0; <span class="docutils literal">source_maximum</span>, <span class="docutils literal">target_maximum</span> / none; <span class="docutils literal">source_navigable</span>, <span class="docutils literal">target_navigable</span> / false</p></td>
|
||||
</tr>
|
||||
<tr><td><p><span class="docutils literal">interaction</span></p></td>
|
||||
<td><p>OA activity → OA activity</p></td>
|
||||
<td><p><span class="docutils literal">items</span> refs / []</p></td>
|
||||
@@ -963,7 +970,8 @@ references. Their kind is the declaration keyword:</p>
|
||||
</table>
|
||||
<p>Relation endpoints and carried ExchangeItems stay in the same layer. Parallel
|
||||
exchanges with distinct identities are permitted. Self-relations are invalid
|
||||
except for a state transition that returns to its source state.</p>
|
||||
except for a state transition that returns to its source state or an explicit
|
||||
DataAssociation between two ends of the same Record type.</p>
|
||||
<p>Direct Allocation has at most one performer per leaf. Role sharing is a
|
||||
different relationship: several OA participants can realize a Role. A direct
|
||||
allocation inconsistent with its role's realized performers produces an
|
||||
@@ -1011,12 +1019,13 @@ not create endpoints. Graphical/command FE creation plans ports atomically,
|
||||
using unique compatible typed-port reuse or deterministic new endpoints.
|
||||
Port deletion cascades to incident FEs; FE deletion retains independent ports.</p>
|
||||
<p>For example:</p>
|
||||
<pre class="literal-block">arcadia 3;
|
||||
<pre class="literal-block">arcadia 4;
|
||||
project ports_example "Typed function contract" {
|
||||
sa_function send "Send" {}
|
||||
sa_function receive "Receive" {}
|
||||
sa_exchange_item payload "Payload" {}
|
||||
sa_interface old_service "Preserved service" { items [@payload]; }
|
||||
sa_interface old_service "Preserved service" {}
|
||||
interface_item_allocation service_payload "Service payload" { source @old_service; target @payload; }
|
||||
sa_port output "Output" {
|
||||
parent @send;
|
||||
contract { FunctionOutput { outgoing_items [@payload]; }; };
|
||||
@@ -1125,11 +1134,19 @@ local to its sender lifeline, has no global exchange or values, and has either
|
||||
no receiver or the same receiver as sender. Its nonempty expression describes
|
||||
the delay/deadline; an empty expression warns. Conditions and expressions are
|
||||
stored engineering annotations, not an executable simulation language.</p>
|
||||
<p>Each MessageValue is <span class="docutils literal">{ field @data_field; expression "value expression"; }</span>.
|
||||
The field MUST be a DataField carried by the message exchange, including fields
|
||||
inside named nested records. At most one annotation for a given field is
|
||||
allowed in one message. Values do not overwrite the referenced type or global
|
||||
exchange item. Expression text is preserved exactly; an empty expression warns.</p>
|
||||
<p>Each MessageValue is <span class="docutils literal">{ path [@parameter]; field @data_field; expression "value expression"; }</span>.
|
||||
Its identity is the pair (path, field), so two uses of one Record can have
|
||||
different values for the same terminal field. Path contains enclosing DataField
|
||||
references, excluding the terminal field; direct parameters use <span class="docutils literal">[]</span>. Every
|
||||
hop MUST follow Value storage through a named Record's effective fields. Reference
|
||||
storage stops traversal. Operation Call accepts In/InOut and Reply accepts
|
||||
Out/InOut/Return, interpreted from the provider's perspective. Nested field paths
|
||||
inherit their direct parameter's direction. Unspecified direction warns.
|
||||
At most one annotation for a pair is allowed. Omitted path defaults to <span class="docutils literal">[]</span>;
|
||||
an ambiguous preserved legacy nested annotation warns <span class="docutils literal">message_value_ambiguous_path</span>
|
||||
until an explicit path is selected. New graphical choices always identify a path.
|
||||
Values never overwrite types or items. Expression text is descriptive, preserved
|
||||
exactly and not evaluated; an empty expression warns.</p>
|
||||
<p>ScenarioUse references an existing same-layer scenario and maps its lifelines
|
||||
with <span class="docutils literal">bindings [ { referenced @callee_line; local @caller_line; } ];</span>.
|
||||
Each binding is one-to-one and references a direct lifeline of the appropriate
|
||||
@@ -1280,6 +1297,137 @@ DeepHistory remembers nested configuration. Fallback applies when no resumable
|
||||
history exists. History is per Region, including top-level Regions in this
|
||||
Studio profile; no running history state is persisted or synthesized.</p>
|
||||
</section>
|
||||
<section id="data-contracts-specialization-and-interface-allocation">
|
||||
<h3>4.5. Data contracts, specialization and interface allocation</h3>
|
||||
<p>ExchangeItem <span class="docutils literal">kind</span> describes nature: Information, Material or Energy.
|
||||
<span class="docutils literal">mechanism</span> is Unspecified, Flow, Event, Operation or SharedData. Unknown
|
||||
mechanisms remain explicit Unspecified drafts with a warning. Material/Energy
|
||||
with Event/Operation/SharedData warns for engineering review; it is not silently
|
||||
reclassified. Empty Event notifications and void Operations are valid. An empty
|
||||
carried/allocated Flow, SharedData or Unspecified item warns.</p>
|
||||
<p>An Operation's directly owned DataFields are parameters. <span class="docutils literal">direction</span> is
|
||||
Unspecified, In, Out, InOut or Return, from the provider's perspective. At most
|
||||
one effective parameter is Return. Unspecified parameters warn; non-operation
|
||||
fields MUST use Unspecified. Nested record fields inherit direction from their
|
||||
direct parameter when used in message paths, rather than storing context on a
|
||||
shared type. <span class="docutils literal">storage</span> is Value or Reference. Reference requires a named Record,
|
||||
has no explicit default, and does not convey ownership or deletion of the type.</p>
|
||||
<p>DataTypeDefinition has exactly the following constructors:</p>
|
||||
<table>
|
||||
<caption>Reusable definitions</caption>
|
||||
<thead>
|
||||
<tr><th class="head"><p>Constructor</p></th>
|
||||
<th class="head"><p>Required fields</p></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><p>Boolean</p></td>
|
||||
<td><p>None</p></td>
|
||||
</tr>
|
||||
<tr><td><p>Integer</p></td>
|
||||
<td><p><span class="docutils literal">minimum</span>, <span class="docutils literal">maximum</span>: optional signed 64-bit integers</p></td>
|
||||
</tr>
|
||||
<tr><td><p>Real</p></td>
|
||||
<td><p><span class="docutils literal">minimum</span>, <span class="docutils literal">maximum</span>: optional finite IEEE-754 binary64 values</p></td>
|
||||
</tr>
|
||||
<tr><td><p>String</p></td>
|
||||
<td><p><span class="docutils literal">minimum_length</span>: u32; <span class="docutils literal">maximum_length</span>: optional u32</p></td>
|
||||
</tr>
|
||||
<tr><td><p>Enumeration</p></td>
|
||||
<td><p><span class="docutils literal">literals</span>: unique nonempty, case-sensitive strings</p></td>
|
||||
</tr>
|
||||
<tr><td><p>Record</p></td>
|
||||
<td><p><span class="docutils literal">supertype</span>: same-layer Record ref?</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Bounds are inclusive and ordered; an absent bound means unbounded within the
|
||||
represented numeric domain. Integer comparisons MUST NOT convert to binary64.
|
||||
NaN, infinities, overflow and reversed bounds reject. String length counts Unicode
|
||||
scalar values, not UTF-8 bytes or grapheme clusters. Enum defaults match exact
|
||||
literals. Empty enum definitions remain incomplete drafts with a warning.</p>
|
||||
<p>DataValue is a tagged scalar: <span class="docutils literal">{ Boolean true; }</span>, <span class="docutils literal">{ Integer 42; }</span>,
|
||||
<span class="docutils literal">{ Real 1.5; }</span>, <span class="docutils literal">{ String "value"; }</span> or <span class="docutils literal">{ Enumeration "Ready"; }</span>.
|
||||
There is no implicit numeric or string coercion. A type default is one compatible
|
||||
scalar within its bounds. Record type defaults and record/object instance literals
|
||||
are unsupported. A field default is absent (<span class="docutils literal">none</span>) or a list of compatible
|
||||
scalars with length inside its multiplicity. <span class="docutils literal">[]</span> explicitly supplies an empty
|
||||
collection and requires minimum 0, including Value Record fields; a nonempty
|
||||
Record literal rejects. Reference fields MUST use <span class="docutils literal">none</span>. A one-valued scalar
|
||||
field uses a one-value list. A named type default supplies an individual element's
|
||||
default, not a collection or an implicit instance of a mandatory field.</p>
|
||||
<p>Numeric types may carry unit text. Empty field units inherit the named type unit;
|
||||
an explicit different unit warns when that type has a unit. Units on nonnumeric
|
||||
fields/types warn and remain preserved. Unit strings never convert values or
|
||||
establish dimensional compatibility. Expressions are not executed.</p>
|
||||
<p>Record, ExchangeItem and Interface each permit one same-family, same-layer
|
||||
supertype. Specialization is acyclic and separate from containment. Effective
|
||||
fields are base fields followed by local fields, preserving original field UUIDs
|
||||
and owners. Local names MUST NOT shadow inherited names. Item specialization
|
||||
preserves base nature and any specified mechanism; an Unspecified base mechanism
|
||||
may be refined. Deleting a derived record never deletes its base. Mandatory
|
||||
Value-field cycles warn <span class="docutils literal">record_no_finite_value</span>; optional or Reference cycles
|
||||
are valid without that warning. Traversal is cycle guarded and bounded; a payload
|
||||
path budget failure is an explicit diagnostic, not silent truncation.</p>
|
||||
<p>InterfaceItemAllocation is an ordinary identified relation from Interface to
|
||||
ExchangeItem. It stores <span class="docutils literal">order</span> and independent transmission/acquisition
|
||||
protocols. Transmission is Unspecified, Synchronous, Asynchronous, Unicast,
|
||||
Multicast or Broadcast; acquisition is Unspecified, Read or Accept. No protocol
|
||||
combination is inferred from mechanism. Effective allocations are base-first,
|
||||
then local ordered by (order, alias, UUID). A local item already allocated locally
|
||||
or inherited is an error. Removing an allocation keeps its item and other
|
||||
allocations; if live boundary compatibility would break, the transaction MUST
|
||||
repair the affected contract explicitly or reject atomically. Artifacts can
|
||||
reference the allocation identity independently of the global item.</p>
|
||||
<p>An exchange carrying a specialized item satisfies a declaration of its base,
|
||||
never the reverse. Standard provided/required compatibility uses explicit
|
||||
interface ancestry. Identity/ancestry, not matching names, defines conformance.
|
||||
The current typed function/component port contracts remain unchanged.</p>
|
||||
<p>DataAssociation connects Record types without adding fields or transitively
|
||||
carrying payload. Each named end has role, multiplicity and navigability. Source
|
||||
multiplicity counts source instances per target instance and vice versa; it is
|
||||
not a count of model elements. An end's navigable flag permits navigation toward
|
||||
that end. Self-associations are valid; if both ends are navigable they require
|
||||
distinct nonempty roles. Empty roles and duplicate role contracts warn, whereas
|
||||
invalid ranges reject. Composition/shared aggregation, multiple inheritance,
|
||||
redefinition, instance literals and arbitrary-precision decimal arithmetic are
|
||||
outside this bounded contract.</p>
|
||||
<p>This complete data contract example is also exercised through the REST API:</p>
|
||||
<pre class="code text literal-block"><code>arcadia 4;
|
||||
project engineering_data "Engineering data" {
|
||||
sa_data_type voltage "Voltage" {
|
||||
definition { Real { minimum 0.0; maximum 48.0; }; };
|
||||
default { Real 24.0; }; unit "V";
|
||||
}
|
||||
sa_data_type coordinate "Coordinate" {
|
||||
definition { Record { supertype none; }; };
|
||||
sa_data_field latitude "Latitude" { type_ref Real; }
|
||||
}
|
||||
sa_data_type located "Located asset" {
|
||||
definition { Record { supertype @coordinate; }; };
|
||||
sa_data_field supply "Supply" { type_ref { Named @voltage; }; }
|
||||
}
|
||||
sa_exchange_item navigate "Navigate" {
|
||||
mechanism Operation;
|
||||
sa_data_field origin "Origin" { type_ref { Named @coordinate; }; direction In; }
|
||||
sa_data_field destination "Destination" { type_ref { Named @coordinate; }; direction In; }
|
||||
sa_data_field accepted "Accepted" { type_ref Boolean; direction Return; }
|
||||
}
|
||||
sa_interface navigation "Navigation" {}
|
||||
sa_interface monitoring "Monitoring" {}
|
||||
interface_item_allocation nav_operation "Navigation operation" {
|
||||
source @navigation; target @navigate; transmission Synchronous; acquisition Accept;
|
||||
}
|
||||
interface_item_allocation monitor_operation "Monitoring operation" {
|
||||
source @monitoring; target @navigate; transmission Asynchronous; acquisition Read;
|
||||
}
|
||||
data_association location_link "Location relationship" {
|
||||
source @coordinate; target @located;
|
||||
source_role "location"; target_role "assets";
|
||||
source_maximum 1;
|
||||
}
|
||||
}</code></pre>
|
||||
</section>
|
||||
</section>
|
||||
<section id="diagrams-artifacts-and-cross-layer-traceability">
|
||||
<h2>5. Diagrams, artifacts, and cross-layer traceability</h2>
|
||||
@@ -1308,7 +1456,7 @@ remove or relocate incompatible placements in the same transaction. Context
|
||||
errors use <span class="docutils literal">state_diagram_context</span>; incompatible placements use
|
||||
<span class="docutils literal">state_diagram_member</span>. Neither case silently hides invalid members.</p>
|
||||
<p>This complete source example places one state from an existing machine:</p>
|
||||
<pre class="code text literal-block"><code>arcadia 3;
|
||||
<pre class="code text literal-block"><code>arcadia 4;
|
||||
project operating "Operating modes" {
|
||||
oa_entity crew "Crew" {}
|
||||
oa_state_machine modes "Modes" { parent @crew; }
|
||||
@@ -1517,7 +1665,7 @@ spellings can be used in alias positions because references begin with <span cla
|
||||
<span class="docutils literal"><span class="pre">element-kind</span></span> and <span class="docutils literal"><span class="pre">relation-kind</span></span> are exactly the corresponding declaration
|
||||
keywords listed above. Typed field
|
||||
sets and enum constructors are closed by sections 3–5.</p>
|
||||
<pre class="code text literal-block"><code>document = "arcadia" "3" ";" project
|
||||
<pre class="code text literal-block"><code>document = "arcadia" "4" ";" project
|
||||
project = "project" alias string identity? "{" project-entry* "}"
|
||||
project-entry = "description" string ";" | declaration
|
||||
declaration = element
|
||||
@@ -1554,16 +1702,16 @@ Ordinary string fields require quoted strings and cannot contain an unquoted
|
||||
<span class="docutils literal">@alias</span> reference. Enum fields require unquoted named values or their typed
|
||||
constructor records. Typed values MUST NOT nest more than 64 levels; malformed
|
||||
deeply nested drafts produce a diagnostic instead of exhausting the parser stack.</p>
|
||||
<section id="modular-source3-projects">
|
||||
<h3>6.1. Modular source3 projects</h3>
|
||||
<section id="modular-source-projects">
|
||||
<h3>6.1. Modular source projects</h3>
|
||||
<p>The pure <span class="docutils literal">source_project</span> core API compiles a virtual source bundle, containing
|
||||
<span class="docutils literal">entry</span> and a <span class="docutils literal">files</span> map from logical paths to UTF-8 strings. Its entry is a
|
||||
root-level <span class="docutils literal">.arcadia</span> file with the source3 project header above. A project entry
|
||||
root-level <span class="docutils literal">.arcadia</span> file with the source4 project header above. A project entry
|
||||
MAY also be <span class="docutils literal">include string ";"</span>. An included fragment consists only of ordinary
|
||||
declarations and include statements; it MUST NOT contain another version header,
|
||||
project wrapper, or project description. Includes MUST occur at document level,
|
||||
never inside an element body or typed field value. For example:</p>
|
||||
<pre class="literal-block">arcadia 3;
|
||||
<pre class="literal-block">arcadia 4;
|
||||
project rescue "Rescue" id "00000000-0000-4000-8000-000000000001" {
|
||||
description "Operational model";
|
||||
include "oa/participants.arcadia";
|
||||
@@ -1621,9 +1769,12 @@ the source index. Columns remain one-based Unicode scalars within the real file;
|
||||
spans never refer to concatenated or synthetic source.</p>
|
||||
<p>Single-string parse/lint APIs remain filesystem-free and reject include
|
||||
statements with an explicit source-bundle requirement. V1/V2 single-file imports
|
||||
continue through their existing migration readers and reports. Modular projects
|
||||
require source3; migration is performed before modular export, not independently
|
||||
on included fragments. Modular source does not change the semantic JSON schema.</p>
|
||||
continue through explicit migration. Modular projects accept source3 and source4;
|
||||
source3 is upgraded as one project, preserving file paths, includes, nested
|
||||
ownership and comments through targeted token edits. Generated allocation
|
||||
declarations stay in their interface's existing file. Individual include fragments
|
||||
are not independently migrated. Missing UUIDs stabilize before migration so new
|
||||
allocation identities are deterministic on subsequent compilation.</p>
|
||||
</section>
|
||||
<section id="nested-element-ownership">
|
||||
<h3>6.2. Nested element ownership</h3>
|
||||
@@ -1827,9 +1978,31 @@ explicitly before Apply succeeds.</p>
|
||||
<h2>9. Persistence and explicit migration</h2>
|
||||
<p>Loading detects JSON from its first non-whitespace <span class="docutils literal">{</span>; other input is parsed
|
||||
as Arcadia source regardless of filename. Saving an <span class="docutils literal">.arcadia</span> suffix uses
|
||||
the accepted V3 source bundle (<span class="docutils literal">arcadia 3</span>); other suffixes use V3 JSON. Both forms preserve the same
|
||||
the accepted V4 source bundle (<span class="docutils literal">arcadia 4</span>); other suffixes use V4 JSON. Both forms preserve the same
|
||||
complete model. JSON rejects unknown fields throughout typed payloads,
|
||||
duplicate maps, unsupported versions, and structural errors.</p>
|
||||
<p>The schema-3 reader freezes the changed data payloads and old constructor catalog;
|
||||
schema-4 fields/constructors MUST NOT be silently accepted as schema 3. Existing
|
||||
typed PortContract records remain unchanged. Information/Material/Energy retain
|
||||
their nature with Unspecified mechanism; old Event becomes Information with Event
|
||||
mechanism. Old bounds/defaults/supertypes are absent, String length is 0..unbounded,
|
||||
and fields retain type/multiplicity/unit with Unspecified direction, Value storage
|
||||
and no explicit default. No physical mechanism or direction is guessed.</p>
|
||||
<p>Each old Interface.items entry generates one InterfaceItemAllocation with its
|
||||
original zero-based order and Unspecified protocols. UUID v5 uses the project UUID
|
||||
namespace and name <span class="docutils literal"><span class="pre">v2-interface-item:<interface-uuid>:<item-uuid></span></span> consistently
|
||||
for schema-2 and schema-3 inputs. Aliases are deterministic and collision-free;
|
||||
collision with any existing identity is an error rather than an overwrite. Existing
|
||||
interface/item identities remain intact. Old nested message values acquire a path
|
||||
only when exactly one valid path exists. Ambiguous paths, including recursive
|
||||
reuse, retain the old annotation with a located warning rather than guessing.</p>
|
||||
<p>Migration reports additionally contain <span class="docutils literal">semantic_defaults</span> (object, field,
|
||||
description), <span class="docutils literal">generated_interface_allocations</span> (id, source, target, alias,
|
||||
order) and <span class="docutils literal">unresolved_message_values</span> (occurrence, field, reason). These new
|
||||
report arrays default empty when reading older responses. Version 1 normalizes
|
||||
through V2, then the typed-port V3 adapter and this shared V4 data upgrade. Original
|
||||
V2 and real V3 fixtures remain unchanged compatibility inputs. Current exports
|
||||
always use version 4; reading/migrating alone never saves or changes revisions.</p>
|
||||
<p>Native source Save All checks the original contents of observed dependencies
|
||||
before staging writes. Existing target files are replaced individually and the
|
||||
entry is installed last. A transaction journal records originals and intended
|
||||
@@ -1853,7 +2026,7 @@ defaults without changing any prior identity, name, reference, order, geometry,
|
||||
artifact or trace field. The original V2 golden source/JSON in
|
||||
<span class="docutils literal"><span class="pre">crates/oa-core/tests/fixtures</span></span> MUST NOT be regenerated from the newer demo;
|
||||
they verify that every old persistent field survives. Canonical output writes
|
||||
the added defaults through the explicit schema-3 migration.</p>
|
||||
the added defaults through the explicit schema-3 and schema-4 migrations.</p>
|
||||
<p>The V2 adapter preserves every original identity, alias, prose, parent,
|
||||
placement, trace and artifact. Generic ports become Legacy with their original
|
||||
direction/interface record. Existing FE endpoint IDs remain unchanged. For
|
||||
@@ -1870,13 +2043,13 @@ IDs, required resolutions, generated endpoint IDs/aliases/owners, and boundary
|
||||
orientation defaults. REST import, replacement, candidate validation and
|
||||
project snapshots surface the same report. Opening an old server envelope
|
||||
preserves its resource ID/revision and bytes; the next explicit edit writes
|
||||
schema 3. Model/source exports contain only the canonical model. Migration
|
||||
schema 4. Model/source exports contain only the canonical model. Migration
|
||||
reports are transient response metadata, not persisted model facts.</p>
|
||||
<p>Admission checks account for generated objects and their references before
|
||||
construction. Both the old V2 contract and the resulting V3 graph are
|
||||
construction. Both the old V2 contract and the resulting V4 graph are
|
||||
validated. Migration itself does not save or increase a stored revision.
|
||||
Canonical second saves are stable. V1 normalization produces the frozen V2
|
||||
model and then uses this same V2-to-3 stage.</p>
|
||||
model and then uses these same V2-to-3-to-4 stages.</p>
|
||||
<p>Save validates a snapshot, writes a sibling temporary file, flushes it, and
|
||||
atomically replaces the destination. Failed serialization or validation must
|
||||
not truncate a previous file. External concurrent-writer conflict resolution
|
||||
@@ -1892,20 +2065,20 @@ step becomes a distinct occurrence element owned by its process. Generated
|
||||
diagram, node, and occurrence identities use UUID v5 with the old Project ID
|
||||
as namespace and deterministic role/index names. If such an identity collides,
|
||||
a deterministic suffix is tried. Reimporting the same fully identified V1
|
||||
input therefore yields the same V3 result, including repeated occurrences.
|
||||
input therefore yields the same V4 result, including repeated occurrences.
|
||||
No System or SA content is invented during an OA-only migration.</p>
|
||||
<p>V1 source aliases are retained when valid in V2. JSON imports generate the old
|
||||
canonical aliases deterministically. Any alias newly reserved in V2 is changed
|
||||
by a deterministic suffix; aliases were not persistent V1 semantic data.
|
||||
A project alias and aliases for new records are generated without colliding
|
||||
with retained aliases. The existing bundled V1 text and JSON migrate to equal
|
||||
V3 projects. Future versions remain errors until a separate migration exists.</p>
|
||||
V4 projects. Future versions remain errors until a separate migration exists.</p>
|
||||
</section>
|
||||
<section id="complete-authoring-example">
|
||||
<h2>10. Complete authoring example</h2>
|
||||
<p>This document intentionally omits IDs for new authoring. Apply and Save write
|
||||
the assigned UUIDs explicitly.</p>
|
||||
<pre class="code text literal-block"><code>arcadia 3;
|
||||
<pre class="code text literal-block"><code>arcadia 4;
|
||||
project harbor "Harbor assistance" {
|
||||
oa_entity control "Harbor control" {}
|
||||
oa_activity assess "Assess assistance" {}
|
||||
|
||||
+219
-41
@@ -1,7 +1,7 @@
|
||||
Arcadia Studio OA / SA Language and Editing Contract
|
||||
====================================================
|
||||
|
||||
:Version: 3
|
||||
:Version: 4
|
||||
:Status: Normative current implementation contract; first-release integration
|
||||
:Core implementation: ``crates/oa-core``
|
||||
:Text suffix: ``.arcadia``
|
||||
@@ -11,15 +11,14 @@ Arcadia Studio OA / SA Language and Editing Contract
|
||||
|
||||
This specification defines the shared Operational Analysis (OA) and System
|
||||
Analysis (SA) model, its textual language, graphical editing obligations,
|
||||
validation, persistence, and explicit migration from versions 1 and 2. MUST, MUST NOT,
|
||||
validation, persistence, and explicit migration from versions 1, 2 and 3. MUST, MUST NOT,
|
||||
and MAY indicate requirements, prohibitions, and permitted choices.
|
||||
|
||||
Schema 3 introduces typed function and component ports, required functional
|
||||
exchange endpoints, independently oriented boundary exchanges, and explicit
|
||||
PortAllocation relations. First-release scenario/state additions remain in
|
||||
scope; this schema change does not declare native acceptance or the wider
|
||||
release complete. The preserved schema-2 reader validates the original
|
||||
contract before migration.
|
||||
Schema 4 adds bounded reusable data types, typed scalar defaults, exchange
|
||||
mechanisms, qualified message values, specialization, identified interface
|
||||
allocations and reference associations. It retains schema 3 typed ports and
|
||||
state views. Explicit older readers preserve existing meanings and identities.
|
||||
This contract does not by itself establish native acceptance or release completion.
|
||||
|
||||
OA describes stakeholders, operational work and needs. SA describes the
|
||||
selected system boundary, external actors, functions, services and expected
|
||||
@@ -40,7 +39,7 @@ Actual verification evidence is separate from this contract.
|
||||
2. One authoritative model
|
||||
--------------------------
|
||||
|
||||
A Project stores ``schema_version`` (3), ``id``, ``alias``, ``name``,
|
||||
A Project stores ``schema_version`` (4), ``id``, ``alias``, ``name``,
|
||||
``description``, and maps named ``elements``, ``relations``, ``diagrams``,
|
||||
``artifact_links``, and ``traces``. Each map is keyed by the UUID contained in
|
||||
its record. Duplicate map keys and mismatching keys/identities are errors.
|
||||
@@ -96,17 +95,17 @@ lists all additional fields. ``ref`` means ``@alias``; ``ref?`` also accepts
|
||||
- ``steps``: occurrence refs
|
||||
- ``[]``
|
||||
* - ``oa_exchange_item``, ``sa_exchange_item``
|
||||
- ``kind``: Information, Material, Energy, Event
|
||||
- Information
|
||||
- ``kind``: Information, Material, Energy; ``mechanism``: ExchangeMechanism; ``supertype``: item ref?
|
||||
- Information; Unspecified; none
|
||||
* - ``oa_data_type``, ``sa_data_type``
|
||||
- ``definition``: Boolean, Integer, Real, String, Record, or Enumeration constructor
|
||||
- String
|
||||
- ``definition``: DataTypeDefinition; ``default``: DataValue?; ``unit``: string
|
||||
- String with minimum_length 0 / maximum_length none; none; ``""``
|
||||
* - ``oa_data_field``, ``sa_data_field``
|
||||
- ``type_ref``; ``minimum``: u32; ``maximum``: optional u32; ``unit``: string
|
||||
- String; 1; 1; ``""``
|
||||
- ``type_ref``; ``minimum``: u32; ``maximum``: optional u32; ``unit``: string; ``direction``: ParameterDirection; ``storage``: FieldStorage; ``default``: DataValue list?
|
||||
- String; 1; 1; ``""``; Unspecified; Value; none
|
||||
* - ``oa_interface``, ``sa_interface``
|
||||
- ``items``: exchange-item refs
|
||||
- ``[]``
|
||||
- ``supertype``: interface ref?
|
||||
- none; membership is an identified interface_item_allocation relation
|
||||
* - ``oa_port``, ``sa_port``
|
||||
- ``contract``: required PortContract; ``legacy``: optional LegacyPortContract
|
||||
- No implicit contract; ``legacy`` defaults none. OA admits Legacy only.
|
||||
@@ -230,6 +229,12 @@ references. Their kind is the declaration keyword:
|
||||
* - ``allocation``
|
||||
- Same-layer participant → leaf activity/function
|
||||
- None
|
||||
* - ``interface_item_allocation``
|
||||
- Same-layer Interface → ExchangeItem
|
||||
- ``order`` u32 / 0; ``transmission`` TransmissionProtocol / Unspecified; ``acquisition`` AcquisitionProtocol / Unspecified
|
||||
* - ``data_association``
|
||||
- Same-layer Record DataType → Record DataType
|
||||
- ``source_role``, ``target_role`` / ""; ``source_minimum``, ``target_minimum`` / 0; ``source_maximum``, ``target_maximum`` / none; ``source_navigable``, ``target_navigable`` / false
|
||||
* - ``interaction``
|
||||
- OA activity → OA activity
|
||||
- ``items`` refs / []
|
||||
@@ -290,7 +295,8 @@ references. Their kind is the declaration keyword:
|
||||
|
||||
Relation endpoints and carried ExchangeItems stay in the same layer. Parallel
|
||||
exchanges with distinct identities are permitted. Self-relations are invalid
|
||||
except for a state transition that returns to its source state.
|
||||
except for a state transition that returns to its source state or an explicit
|
||||
DataAssociation between two ends of the same Record type.
|
||||
|
||||
Direct Allocation has at most one performer per leaf. Role sharing is a
|
||||
different relationship: several OA participants can realize a Role. A direct
|
||||
@@ -347,12 +353,13 @@ Port deletion cascades to incident FEs; FE deletion retains independent ports.
|
||||
|
||||
For example::
|
||||
|
||||
arcadia 3;
|
||||
arcadia 4;
|
||||
project ports_example "Typed function contract" {
|
||||
sa_function send "Send" {}
|
||||
sa_function receive "Receive" {}
|
||||
sa_exchange_item payload "Payload" {}
|
||||
sa_interface old_service "Preserved service" { items [@payload]; }
|
||||
sa_interface old_service "Preserved service" {}
|
||||
interface_item_allocation service_payload "Service payload" { source @old_service; target @payload; }
|
||||
sa_port output "Output" {
|
||||
parent @send;
|
||||
contract { FunctionOutput { outgoing_items [@payload]; }; };
|
||||
@@ -474,11 +481,19 @@ no receiver or the same receiver as sender. Its nonempty expression describes
|
||||
the delay/deadline; an empty expression warns. Conditions and expressions are
|
||||
stored engineering annotations, not an executable simulation language.
|
||||
|
||||
Each MessageValue is ``{ field @data_field; expression "value expression"; }``.
|
||||
The field MUST be a DataField carried by the message exchange, including fields
|
||||
inside named nested records. At most one annotation for a given field is
|
||||
allowed in one message. Values do not overwrite the referenced type or global
|
||||
exchange item. Expression text is preserved exactly; an empty expression warns.
|
||||
Each MessageValue is ``{ path [@parameter]; field @data_field; expression "value expression"; }``.
|
||||
Its identity is the pair (path, field), so two uses of one Record can have
|
||||
different values for the same terminal field. Path contains enclosing DataField
|
||||
references, excluding the terminal field; direct parameters use ``[]``. Every
|
||||
hop MUST follow Value storage through a named Record's effective fields. Reference
|
||||
storage stops traversal. Operation Call accepts In/InOut and Reply accepts
|
||||
Out/InOut/Return, interpreted from the provider's perspective. Nested field paths
|
||||
inherit their direct parameter's direction. Unspecified direction warns.
|
||||
At most one annotation for a pair is allowed. Omitted path defaults to ``[]``;
|
||||
an ambiguous preserved legacy nested annotation warns ``message_value_ambiguous_path``
|
||||
until an explicit path is selected. New graphical choices always identify a path.
|
||||
Values never overwrite types or items. Expression text is descriptive, preserved
|
||||
exactly and not evaluated; an empty expression warns.
|
||||
|
||||
ScenarioUse references an existing same-layer scenario and maps its lifelines
|
||||
with ``bindings [ { referenced @callee_line; local @caller_line; } ];``.
|
||||
@@ -620,6 +635,141 @@ DeepHistory remembers nested configuration. Fallback applies when no resumable
|
||||
history exists. History is per Region, including top-level Regions in this
|
||||
Studio profile; no running history state is persisted or synthesized.
|
||||
|
||||
4.5. Data contracts, specialization and interface allocation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ExchangeItem ``kind`` describes nature: Information, Material or Energy.
|
||||
``mechanism`` is Unspecified, Flow, Event, Operation or SharedData. Unknown
|
||||
mechanisms remain explicit Unspecified drafts with a warning. Material/Energy
|
||||
with Event/Operation/SharedData warns for engineering review; it is not silently
|
||||
reclassified. Empty Event notifications and void Operations are valid. An empty
|
||||
carried/allocated Flow, SharedData or Unspecified item warns.
|
||||
|
||||
An Operation's directly owned DataFields are parameters. ``direction`` is
|
||||
Unspecified, In, Out, InOut or Return, from the provider's perspective. At most
|
||||
one effective parameter is Return. Unspecified parameters warn; non-operation
|
||||
fields MUST use Unspecified. Nested record fields inherit direction from their
|
||||
direct parameter when used in message paths, rather than storing context on a
|
||||
shared type. ``storage`` is Value or Reference. Reference requires a named Record,
|
||||
has no explicit default, and does not convey ownership or deletion of the type.
|
||||
|
||||
DataTypeDefinition has exactly the following constructors:
|
||||
|
||||
.. list-table:: Reusable definitions
|
||||
:header-rows: 1
|
||||
|
||||
* - Constructor
|
||||
- Required fields
|
||||
* - Boolean
|
||||
- None
|
||||
* - Integer
|
||||
- ``minimum``, ``maximum``: optional signed 64-bit integers
|
||||
* - Real
|
||||
- ``minimum``, ``maximum``: optional finite IEEE-754 binary64 values
|
||||
* - String
|
||||
- ``minimum_length``: u32; ``maximum_length``: optional u32
|
||||
* - Enumeration
|
||||
- ``literals``: unique nonempty, case-sensitive strings
|
||||
* - Record
|
||||
- ``supertype``: same-layer Record ref?
|
||||
|
||||
Bounds are inclusive and ordered; an absent bound means unbounded within the
|
||||
represented numeric domain. Integer comparisons MUST NOT convert to binary64.
|
||||
NaN, infinities, overflow and reversed bounds reject. String length counts Unicode
|
||||
scalar values, not UTF-8 bytes or grapheme clusters. Enum defaults match exact
|
||||
literals. Empty enum definitions remain incomplete drafts with a warning.
|
||||
|
||||
DataValue is a tagged scalar: ``{ Boolean true; }``, ``{ Integer 42; }``,
|
||||
``{ Real 1.5; }``, ``{ String "value"; }`` or ``{ Enumeration "Ready"; }``.
|
||||
There is no implicit numeric or string coercion. A type default is one compatible
|
||||
scalar within its bounds. Record type defaults and record/object instance literals
|
||||
are unsupported. A field default is absent (``none``) or a list of compatible
|
||||
scalars with length inside its multiplicity. ``[]`` explicitly supplies an empty
|
||||
collection and requires minimum 0, including Value Record fields; a nonempty
|
||||
Record literal rejects. Reference fields MUST use ``none``. A one-valued scalar
|
||||
field uses a one-value list. A named type default supplies an individual element's
|
||||
default, not a collection or an implicit instance of a mandatory field.
|
||||
|
||||
Numeric types may carry unit text. Empty field units inherit the named type unit;
|
||||
an explicit different unit warns when that type has a unit. Units on nonnumeric
|
||||
fields/types warn and remain preserved. Unit strings never convert values or
|
||||
establish dimensional compatibility. Expressions are not executed.
|
||||
|
||||
Record, ExchangeItem and Interface each permit one same-family, same-layer
|
||||
supertype. Specialization is acyclic and separate from containment. Effective
|
||||
fields are base fields followed by local fields, preserving original field UUIDs
|
||||
and owners. Local names MUST NOT shadow inherited names. Item specialization
|
||||
preserves base nature and any specified mechanism; an Unspecified base mechanism
|
||||
may be refined. Deleting a derived record never deletes its base. Mandatory
|
||||
Value-field cycles warn ``record_no_finite_value``; optional or Reference cycles
|
||||
are valid without that warning. Traversal is cycle guarded and bounded; a payload
|
||||
path budget failure is an explicit diagnostic, not silent truncation.
|
||||
|
||||
InterfaceItemAllocation is an ordinary identified relation from Interface to
|
||||
ExchangeItem. It stores ``order`` and independent transmission/acquisition
|
||||
protocols. Transmission is Unspecified, Synchronous, Asynchronous, Unicast,
|
||||
Multicast or Broadcast; acquisition is Unspecified, Read or Accept. No protocol
|
||||
combination is inferred from mechanism. Effective allocations are base-first,
|
||||
then local ordered by (order, alias, UUID). A local item already allocated locally
|
||||
or inherited is an error. Removing an allocation keeps its item and other
|
||||
allocations; if live boundary compatibility would break, the transaction MUST
|
||||
repair the affected contract explicitly or reject atomically. Artifacts can
|
||||
reference the allocation identity independently of the global item.
|
||||
|
||||
An exchange carrying a specialized item satisfies a declaration of its base,
|
||||
never the reverse. Standard provided/required compatibility uses explicit
|
||||
interface ancestry. Identity/ancestry, not matching names, defines conformance.
|
||||
The current typed function/component port contracts remain unchanged.
|
||||
|
||||
DataAssociation connects Record types without adding fields or transitively
|
||||
carrying payload. Each named end has role, multiplicity and navigability. Source
|
||||
multiplicity counts source instances per target instance and vice versa; it is
|
||||
not a count of model elements. An end's navigable flag permits navigation toward
|
||||
that end. Self-associations are valid; if both ends are navigable they require
|
||||
distinct nonempty roles. Empty roles and duplicate role contracts warn, whereas
|
||||
invalid ranges reject. Composition/shared aggregation, multiple inheritance,
|
||||
redefinition, instance literals and arbitrary-precision decimal arithmetic are
|
||||
outside this bounded contract.
|
||||
|
||||
This complete data contract example is also exercised through the REST API:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
arcadia 4;
|
||||
project engineering_data "Engineering data" {
|
||||
sa_data_type voltage "Voltage" {
|
||||
definition { Real { minimum 0.0; maximum 48.0; }; };
|
||||
default { Real 24.0; }; unit "V";
|
||||
}
|
||||
sa_data_type coordinate "Coordinate" {
|
||||
definition { Record { supertype none; }; };
|
||||
sa_data_field latitude "Latitude" { type_ref Real; }
|
||||
}
|
||||
sa_data_type located "Located asset" {
|
||||
definition { Record { supertype @coordinate; }; };
|
||||
sa_data_field supply "Supply" { type_ref { Named @voltage; }; }
|
||||
}
|
||||
sa_exchange_item navigate "Navigate" {
|
||||
mechanism Operation;
|
||||
sa_data_field origin "Origin" { type_ref { Named @coordinate; }; direction In; }
|
||||
sa_data_field destination "Destination" { type_ref { Named @coordinate; }; direction In; }
|
||||
sa_data_field accepted "Accepted" { type_ref Boolean; direction Return; }
|
||||
}
|
||||
sa_interface navigation "Navigation" {}
|
||||
sa_interface monitoring "Monitoring" {}
|
||||
interface_item_allocation nav_operation "Navigation operation" {
|
||||
source @navigation; target @navigate; transmission Synchronous; acquisition Accept;
|
||||
}
|
||||
interface_item_allocation monitor_operation "Monitoring operation" {
|
||||
source @monitoring; target @navigate; transmission Asynchronous; acquisition Read;
|
||||
}
|
||||
data_association location_link "Location relationship" {
|
||||
source @coordinate; target @located;
|
||||
source_role "location"; target_role "assets";
|
||||
source_maximum 1;
|
||||
}
|
||||
}
|
||||
|
||||
5. Diagrams, artifacts, and cross-layer traceability
|
||||
----------------------------------------------------
|
||||
|
||||
@@ -654,7 +804,7 @@ This complete source example places one state from an existing machine:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
arcadia 3;
|
||||
arcadia 4;
|
||||
project operating "Operating modes" {
|
||||
oa_entity crew "Crew" {}
|
||||
oa_state_machine modes "Modes" { parent @crew; }
|
||||
@@ -875,7 +1025,7 @@ sets and enum constructors are closed by sections 3–5.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
document = "arcadia" "3" ";" project
|
||||
document = "arcadia" "4" ";" project
|
||||
project = "project" alias string identity? "{" project-entry* "}"
|
||||
project-entry = "description" string ";" | declaration
|
||||
declaration = element
|
||||
@@ -917,18 +1067,18 @@ Ordinary string fields require quoted strings and cannot contain an unquoted
|
||||
constructor records. Typed values MUST NOT nest more than 64 levels; malformed
|
||||
deeply nested drafts produce a diagnostic instead of exhausting the parser stack.
|
||||
|
||||
6.1. Modular source3 projects
|
||||
6.1. Modular source projects
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The pure ``source_project`` core API compiles a virtual source bundle, containing
|
||||
``entry`` and a ``files`` map from logical paths to UTF-8 strings. Its entry is a
|
||||
root-level ``.arcadia`` file with the source3 project header above. A project entry
|
||||
root-level ``.arcadia`` file with the source4 project header above. A project entry
|
||||
MAY also be ``include string ";"``. An included fragment consists only of ordinary
|
||||
declarations and include statements; it MUST NOT contain another version header,
|
||||
project wrapper, or project description. Includes MUST occur at document level,
|
||||
never inside an element body or typed field value. For example::
|
||||
|
||||
arcadia 3;
|
||||
arcadia 4;
|
||||
project rescue "Rescue" id "00000000-0000-4000-8000-000000000001" {
|
||||
description "Operational model";
|
||||
include "oa/participants.arcadia";
|
||||
@@ -994,9 +1144,12 @@ spans never refer to concatenated or synthetic source.
|
||||
|
||||
Single-string parse/lint APIs remain filesystem-free and reject include
|
||||
statements with an explicit source-bundle requirement. V1/V2 single-file imports
|
||||
continue through their existing migration readers and reports. Modular projects
|
||||
require source3; migration is performed before modular export, not independently
|
||||
on included fragments. Modular source does not change the semantic JSON schema.
|
||||
continue through explicit migration. Modular projects accept source3 and source4;
|
||||
source3 is upgraded as one project, preserving file paths, includes, nested
|
||||
ownership and comments through targeted token edits. Generated allocation
|
||||
declarations stay in their interface's existing file. Individual include fragments
|
||||
are not independently migrated. Missing UUIDs stabilize before migration so new
|
||||
allocation identities are deterministic on subsequent compilation.
|
||||
|
||||
6.2. Nested element ownership
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -1228,10 +1381,35 @@ explicitly before Apply succeeds.
|
||||
|
||||
Loading detects JSON from its first non-whitespace ``{``; other input is parsed
|
||||
as Arcadia source regardless of filename. Saving an ``.arcadia`` suffix uses
|
||||
the accepted V3 source bundle (``arcadia 3``); other suffixes use V3 JSON. Both forms preserve the same
|
||||
the accepted V4 source bundle (``arcadia 4``); other suffixes use V4 JSON. Both forms preserve the same
|
||||
complete model. JSON rejects unknown fields throughout typed payloads,
|
||||
duplicate maps, unsupported versions, and structural errors.
|
||||
|
||||
The schema-3 reader freezes the changed data payloads and old constructor catalog;
|
||||
schema-4 fields/constructors MUST NOT be silently accepted as schema 3. Existing
|
||||
typed PortContract records remain unchanged. Information/Material/Energy retain
|
||||
their nature with Unspecified mechanism; old Event becomes Information with Event
|
||||
mechanism. Old bounds/defaults/supertypes are absent, String length is 0..unbounded,
|
||||
and fields retain type/multiplicity/unit with Unspecified direction, Value storage
|
||||
and no explicit default. No physical mechanism or direction is guessed.
|
||||
|
||||
Each old Interface.items entry generates one InterfaceItemAllocation with its
|
||||
original zero-based order and Unspecified protocols. UUID v5 uses the project UUID
|
||||
namespace and name ``v2-interface-item:<interface-uuid>:<item-uuid>`` consistently
|
||||
for schema-2 and schema-3 inputs. Aliases are deterministic and collision-free;
|
||||
collision with any existing identity is an error rather than an overwrite. Existing
|
||||
interface/item identities remain intact. Old nested message values acquire a path
|
||||
only when exactly one valid path exists. Ambiguous paths, including recursive
|
||||
reuse, retain the old annotation with a located warning rather than guessing.
|
||||
|
||||
Migration reports additionally contain ``semantic_defaults`` (object, field,
|
||||
description), ``generated_interface_allocations`` (id, source, target, alias,
|
||||
order) and ``unresolved_message_values`` (occurrence, field, reason). These new
|
||||
report arrays default empty when reading older responses. Version 1 normalizes
|
||||
through V2, then the typed-port V3 adapter and this shared V4 data upgrade. Original
|
||||
V2 and real V3 fixtures remain unchanged compatibility inputs. Current exports
|
||||
always use version 4; reading/migrating alone never saves or changes revisions.
|
||||
|
||||
Native source Save All checks the original contents of observed dependencies
|
||||
before staging writes. Existing target files are replaced individually and the
|
||||
entry is installed last. A transaction journal records originals and intended
|
||||
@@ -1256,7 +1434,7 @@ defaults without changing any prior identity, name, reference, order, geometry,
|
||||
artifact or trace field. The original V2 golden source/JSON in
|
||||
``crates/oa-core/tests/fixtures`` MUST NOT be regenerated from the newer demo;
|
||||
they verify that every old persistent field survives. Canonical output writes
|
||||
the added defaults through the explicit schema-3 migration.
|
||||
the added defaults through the explicit schema-3 and schema-4 migrations.
|
||||
|
||||
The V2 adapter preserves every original identity, alias, prose, parent,
|
||||
placement, trace and artifact. Generic ports become Legacy with their original
|
||||
@@ -1275,14 +1453,14 @@ IDs, required resolutions, generated endpoint IDs/aliases/owners, and boundary
|
||||
orientation defaults. REST import, replacement, candidate validation and
|
||||
project snapshots surface the same report. Opening an old server envelope
|
||||
preserves its resource ID/revision and bytes; the next explicit edit writes
|
||||
schema 3. Model/source exports contain only the canonical model. Migration
|
||||
schema 4. Model/source exports contain only the canonical model. Migration
|
||||
reports are transient response metadata, not persisted model facts.
|
||||
|
||||
Admission checks account for generated objects and their references before
|
||||
construction. Both the old V2 contract and the resulting V3 graph are
|
||||
construction. Both the old V2 contract and the resulting V4 graph are
|
||||
validated. Migration itself does not save or increase a stored revision.
|
||||
Canonical second saves are stable. V1 normalization produces the frozen V2
|
||||
model and then uses this same V2-to-3 stage.
|
||||
model and then uses these same V2-to-3-to-4 stages.
|
||||
|
||||
Save validates a snapshot, writes a sibling temporary file, flushes it, and
|
||||
atomically replaces the destination. Failed serialization or validation must
|
||||
@@ -1301,7 +1479,7 @@ step becomes a distinct occurrence element owned by its process. Generated
|
||||
diagram, node, and occurrence identities use UUID v5 with the old Project ID
|
||||
as namespace and deterministic role/index names. If such an identity collides,
|
||||
a deterministic suffix is tried. Reimporting the same fully identified V1
|
||||
input therefore yields the same V3 result, including repeated occurrences.
|
||||
input therefore yields the same V4 result, including repeated occurrences.
|
||||
No System or SA content is invented during an OA-only migration.
|
||||
|
||||
V1 source aliases are retained when valid in V2. JSON imports generate the old
|
||||
@@ -1309,7 +1487,7 @@ canonical aliases deterministically. Any alias newly reserved in V2 is changed
|
||||
by a deterministic suffix; aliases were not persistent V1 semantic data.
|
||||
A project alias and aliases for new records are generated without colliding
|
||||
with retained aliases. The existing bundled V1 text and JSON migrate to equal
|
||||
V3 projects. Future versions remain errors until a separate migration exists.
|
||||
V4 projects. Future versions remain errors until a separate migration exists.
|
||||
|
||||
10. Complete authoring example
|
||||
------------------------------
|
||||
@@ -1319,7 +1497,7 @@ the assigned UUIDs explicitly.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
arcadia 3;
|
||||
arcadia 4;
|
||||
project harbor "Harbor assistance" {
|
||||
oa_entity control "Harbor control" {}
|
||||
oa_activity assess "Assess assistance" {}
|
||||
|
||||
+652
-63
@@ -3,7 +3,7 @@
|
||||
"info": {
|
||||
"title": "Arcadia Studio model API",
|
||||
"version": "1.0.0",
|
||||
"description": "Current schema-3 snapshots and conditional atomic writes. Request body limit: 8 MiB; at most 200 nested commands; no retained revisions, request receipts, automatic retries or persistent transition plans. See docs/api.rst. Fixed store capacity: 128 models / 256 MiB serialized envelopes. Stateless transition preview/apply. Artifact URI/revision strings remain opaque core fields. Model admission before structural validation: 5,000 graph objects, 20,000 total records and 50,000 ordered references. Preparation uses snapshots outside the catalog lock; final commits recheck the exact ETag. Each accepted envelope couples model and authored source under one revision. Source-only edits advance the shared ETag. Source bundles resolve logical paths only, preserve authored files/comments, and have a stabilized JSON cap of 8 MiB, 256 files, 32 include edges along a path and 1,024 include edges overall."
|
||||
"description": "Current schema-4 snapshots and conditional atomic writes. Request body limit: 8 MiB; at most 200 nested commands; no retained revisions, request receipts, automatic retries or persistent transition plans. See docs/api.rst. Fixed store capacity: 128 models / 256 MiB serialized envelopes. Stateless transition preview/apply. Artifact URI/revision strings remain opaque core fields. Model admission before structural validation: 5,000 graph objects, 20,000 total records and 50,000 ordered references. Preparation uses snapshots outside the catalog lock; final commits recheck the exact ETag. Each accepted envelope couples model and authored source under one revision. Source-only edits advance the shared ETag. Source bundles resolve logical paths only, preserve authored files/comments, and have a stabilized JSON cap of 8 MiB, 256 files, 32 include edges along a path and 1,024 include edges overall."
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
@@ -389,7 +389,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Schema-3 native JSON is described below. Schema-1 and schema-2 JSON/source are accepted through explicit frozen readers and migration, also on replacement and candidate validation. Reports list preserved Legacy contracts, generated FE endpoint IDs/aliases and boundary orientation defaults. Export emits schema 3 / arcadia 3. See docs/language.rst."
|
||||
"description": "Schema-4 native JSON is described below. Schema-1, schema-2 and schema-3 JSON/source are accepted through explicit frozen readers and migration, also on replacement and candidate validation. Reports list preserved Legacy contracts, generated FE endpoint IDs/aliases and boundary orientation defaults. Export emits schema 4 / arcadia 4. See docs/language.rst."
|
||||
}
|
||||
},
|
||||
"/api/v1/projects/{id}": {
|
||||
@@ -1902,7 +1902,9 @@
|
||||
"CapabilityGeneralization",
|
||||
"MissionInvolvement",
|
||||
"SequenceLink",
|
||||
"PortAllocation"
|
||||
"PortAllocation",
|
||||
"InterfaceItemAllocation",
|
||||
"DataAssociation"
|
||||
]
|
||||
},
|
||||
"Position": {
|
||||
@@ -2004,40 +2006,185 @@
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Boolean",
|
||||
"Integer",
|
||||
"Real",
|
||||
"String",
|
||||
"Record"
|
||||
"Boolean"
|
||||
]
|
||||
},
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Integer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Enumeration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"literals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
"minimum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"minimum": -9223372036854775808,
|
||||
"maximum": 9223372036854775807
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"literals"
|
||||
],
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
"maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"minimum": -9223372036854775808,
|
||||
"maximum": 9223372036854775807
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Enumeration"
|
||||
"minimum",
|
||||
"maximum"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"required": [
|
||||
"Integer"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Real": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"minimum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Finite IEEE-754 binary64; no coercion from typed Integer values."
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Finite IEEE-754 binary64; no coercion from typed Integer values."
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"minimum",
|
||||
"maximum"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Real"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"String": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"minimum_length": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"maximum_length": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"minimum_length",
|
||||
"maximum_length"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"String"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Enumeration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"literals": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"literals"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Enumeration"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Record": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"supertype": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"supertype"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Record"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2402,17 +2549,27 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Information",
|
||||
"Material",
|
||||
"Energy",
|
||||
"Event"
|
||||
"$ref": "#/components/schemas/ExchangeItemKind"
|
||||
},
|
||||
"mechanism": {
|
||||
"$ref": "#/components/schemas/ExchangeMechanism"
|
||||
},
|
||||
"supertype": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind"
|
||||
"kind",
|
||||
"mechanism",
|
||||
"supertype"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -2430,10 +2587,25 @@
|
||||
"properties": {
|
||||
"definition": {
|
||||
"$ref": "#/components/schemas/DataTypeDefinition"
|
||||
},
|
||||
"default": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/DataValue"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"definition"
|
||||
"definition",
|
||||
"default",
|
||||
"unit"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -2454,13 +2626,15 @@
|
||||
},
|
||||
"minimum": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
@@ -2469,13 +2643,35 @@
|
||||
},
|
||||
"unit": {
|
||||
"type": "string"
|
||||
},
|
||||
"direction": {
|
||||
"$ref": "#/components/schemas/ParameterDirection"
|
||||
},
|
||||
"storage": {
|
||||
"$ref": "#/components/schemas/FieldStorage"
|
||||
},
|
||||
"default": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DataValue"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type_ref",
|
||||
"minimum",
|
||||
"maximum",
|
||||
"unit"
|
||||
"unit",
|
||||
"direction",
|
||||
"storage",
|
||||
"default"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -2491,16 +2687,20 @@
|
||||
"Interface": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
"supertype": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"items"
|
||||
"supertype"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -3581,6 +3781,128 @@
|
||||
"PortAllocation"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"InterfaceItemAllocation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"transmission": {
|
||||
"$ref": "#/components/schemas/TransmissionProtocol"
|
||||
},
|
||||
"acquisition": {
|
||||
"$ref": "#/components/schemas/AcquisitionProtocol"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source",
|
||||
"target",
|
||||
"order",
|
||||
"transmission",
|
||||
"acquisition"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"InterfaceItemAllocation"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"DataAssociation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"source": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"source_role": {
|
||||
"type": "string"
|
||||
},
|
||||
"target_role": {
|
||||
"type": "string"
|
||||
},
|
||||
"source_minimum": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"source_maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"target_minimum": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"target_maximum": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"source_navigable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"target_navigable": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source",
|
||||
"target",
|
||||
"source_role",
|
||||
"target_role",
|
||||
"source_minimum",
|
||||
"source_maximum",
|
||||
"target_minimum",
|
||||
"target_maximum",
|
||||
"source_navigable",
|
||||
"target_navigable"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"DataAssociation"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -3617,7 +3939,12 @@
|
||||
},
|
||||
"PortAnchorSide": {
|
||||
"type": "string",
|
||||
"enum": ["Left", "Right", "Top", "Bottom"],
|
||||
"enum": [
|
||||
"Left",
|
||||
"Right",
|
||||
"Top",
|
||||
"Bottom"
|
||||
],
|
||||
"description": "Presentation side of the owner placement; independent of semantic port direction."
|
||||
},
|
||||
"PortAnchor": {
|
||||
@@ -3638,7 +3965,11 @@
|
||||
"description": "Finite binary32 fraction of the complete owner edge, measured from top on Left/Right and from left on Top/Bottom."
|
||||
}
|
||||
},
|
||||
"required": ["port", "side", "offset"],
|
||||
"required": [
|
||||
"port",
|
||||
"side",
|
||||
"offset"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"NodePlacement": {
|
||||
@@ -3956,7 +4287,7 @@
|
||||
"properties": {
|
||||
"schema_version": {
|
||||
"type": "integer",
|
||||
"const": 3
|
||||
"const": 4
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
@@ -4070,7 +4401,7 @@
|
||||
"source_project"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"description": "Accepted coupled model/source snapshot. Compiling source_project reproduces model; revision changes once if either representation changes. Old model-only envelopes acquire source in memory without a write or revision change."
|
||||
"description": "Accepted coupled model/source snapshot. Compiling source_project reproduces model; revision changes once if either representation changes. Older model-only or schema3 coupled envelopes migrate in memory without a write or revision change; both representations must independently migrate to the same graph."
|
||||
},
|
||||
"ProjectSummary": {
|
||||
"type": "object",
|
||||
@@ -4814,15 +5145,29 @@
|
||||
"type": "object",
|
||||
"description": "Upsert manual port position by port identity on an existing owner placement, preserving unrelated entries. Port must be a direct child of the placement's semantic element.",
|
||||
"properties": {
|
||||
"diagram": { "type": "string", "format": "uuid" },
|
||||
"node": { "type": "string", "format": "uuid" },
|
||||
"anchor": { "$ref": "#/components/schemas/PortAnchor" }
|
||||
"diagram": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"node": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"anchor": {
|
||||
"$ref": "#/components/schemas/PortAnchor"
|
||||
}
|
||||
},
|
||||
"required": ["diagram", "node", "anchor"],
|
||||
"required": [
|
||||
"diagram",
|
||||
"node",
|
||||
"anchor"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["SetPortAnchor"],
|
||||
"required": [
|
||||
"SetPortAnchor"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
@@ -4832,15 +5177,30 @@
|
||||
"type": "object",
|
||||
"description": "Restore automatic positioning for an existing direct child Port. No-op when that valid owner placement has no manual anchor for the port; wrong or stale ownership is rejected.",
|
||||
"properties": {
|
||||
"diagram": { "type": "string", "format": "uuid" },
|
||||
"node": { "type": "string", "format": "uuid" },
|
||||
"port": { "type": "string", "format": "uuid" }
|
||||
"diagram": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"node": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"port": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"required": ["diagram", "node", "port"],
|
||||
"required": [
|
||||
"diagram",
|
||||
"node",
|
||||
"port"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["RemovePortAnchor"],
|
||||
"required": [
|
||||
"RemovePortAnchor"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
@@ -5809,6 +6169,14 @@
|
||||
"MessageValue": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"field": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
@@ -5821,7 +6189,8 @@
|
||||
"field",
|
||||
"expression"
|
||||
],
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"description": "Identity is (path, field). Path lists enclosing DataField UUIDs, excluding the terminal field. Value storage traverses named Records; Reference storage stops traversal. Operation Call accepts In/InOut and Reply accepts Out/InOut/Return. Unspecified direction and retained ambiguous legacy empty paths warn. Expressions are descriptive, never executed."
|
||||
},
|
||||
"LifelineBinding": {
|
||||
"type": "object",
|
||||
@@ -6083,12 +6452,13 @@
|
||||
"type": "integer",
|
||||
"enum": [
|
||||
1,
|
||||
2
|
||||
2,
|
||||
3
|
||||
]
|
||||
},
|
||||
"to_schema": {
|
||||
"type": "integer",
|
||||
"const": 3
|
||||
"const": 4
|
||||
},
|
||||
"preserved_ports": {
|
||||
"type": "array",
|
||||
@@ -6179,6 +6549,91 @@
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"semantic_defaults": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"object": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"field": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"object",
|
||||
"field",
|
||||
"description"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"generated_interface_allocations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"target": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"alias": {
|
||||
"type": "string"
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"source",
|
||||
"target",
|
||||
"alias",
|
||||
"order"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"unresolved_message_values": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"occurrence": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"field": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"occurrence",
|
||||
"field",
|
||||
"reason"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -6190,11 +6645,11 @@
|
||||
"required_resolutions"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"description": "Transient observations from explicit V1→V2→V3 or V2→V3 migration. No save or revision increase occurs merely by reading an old envelope."
|
||||
"description": "Transient observations from explicit V1/V2/V3 to V4 migration. New report lists default to empty when reading older responses. Reading an old envelope neither saves nor changes its revision. Allocation UUIDv5 uses project namespace and v2-interface-item:<interface>:<item>."
|
||||
},
|
||||
"SourceBundle": {
|
||||
"type": "object",
|
||||
"description": "Complete source3 workspace. The entry is a root filename. Files use canonical portable slash-separated relative .arcadia paths and all must be reachable. Includes resolve only against this map, never the service filesystem. Up to 256 files, 32 include edges along a path and 1,024 include edges overall. Serialized bundle JSON is at most 8 MiB, checked again after missing UUIDs are inserted. GET returns exact accepted stable text.",
|
||||
"description": "Complete source4 workspace (source3 migrates explicitly). The entry is a root filename. Files use canonical portable slash-separated relative .arcadia paths and all must be reachable. Includes resolve only against this map, never the service filesystem. Up to 256 files, 32 include edges along a path and 1,024 include edges overall. Serialized bundle JSON is at most 8 MiB, checked again after missing UUIDs are inserted. GET returns exact accepted stable text.",
|
||||
"properties": {
|
||||
"entry": {
|
||||
"type": "string"
|
||||
@@ -6267,15 +6722,149 @@
|
||||
},
|
||||
"source_project": {
|
||||
"$ref": "#/components/schemas/SourceBundle"
|
||||
},
|
||||
"migration": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/MigrationReport"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"revision",
|
||||
"changed",
|
||||
"issues",
|
||||
"source_project"
|
||||
"source_project",
|
||||
"migration"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"ExchangeItemKind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Information",
|
||||
"Material",
|
||||
"Energy"
|
||||
]
|
||||
},
|
||||
"ExchangeMechanism": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Unspecified",
|
||||
"Flow",
|
||||
"Event",
|
||||
"Operation",
|
||||
"SharedData"
|
||||
]
|
||||
},
|
||||
"ParameterDirection": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Unspecified",
|
||||
"In",
|
||||
"Out",
|
||||
"InOut",
|
||||
"Return"
|
||||
]
|
||||
},
|
||||
"FieldStorage": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Value",
|
||||
"Reference"
|
||||
]
|
||||
},
|
||||
"TransmissionProtocol": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Unspecified",
|
||||
"Synchronous",
|
||||
"Asynchronous",
|
||||
"Unicast",
|
||||
"Multicast",
|
||||
"Broadcast"
|
||||
]
|
||||
},
|
||||
"AcquisitionProtocol": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Unspecified",
|
||||
"Read",
|
||||
"Accept"
|
||||
]
|
||||
},
|
||||
"DataValue": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Boolean": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Boolean"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Integer": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"minimum": -9223372036854775808,
|
||||
"maximum": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Integer"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Real": {
|
||||
"type": "number",
|
||||
"format": "double",
|
||||
"description": "Finite IEEE-754 binary64; no coercion from typed Integer values."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Real"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"String": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"String"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Enumeration": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Enumeration"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+33
-7
@@ -11,7 +11,7 @@ attachment07aee762-7d27-4cbe-81c3-2e82c7170711/goal-objective.md.
|
||||
PLAN.md retains the entire release scope; no subsystem acceptance completes it.
|
||||
|
||||
Direct state-machine editing is accepted through production316dc55. The main
|
||||
checkout can fast-forward to this integration. R6 data/interface contracts are now
|
||||
checkout was fast-forwarded to acceptance a8f451e. R6 data/interface contracts are now
|
||||
being implemented in a separate checkout; they are not accepted or released.
|
||||
Meaningful implementation and runtime progress continues; no external blocker exists.
|
||||
|
||||
@@ -76,13 +76,39 @@ 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.
|
||||
|
||||
Ownership: data_core owns core model/data/validation/references/ports/transitions
|
||||
and non-source tests; state_architecture_review owns source/migration/persistence
|
||||
and their tests; drawing_correctness owns desktop. Root owns API/OpenAPI/reST,
|
||||
integration and native input. Do not edit workers' files or reset their changes.
|
||||
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 (final allocation-arrow suppression arrived
|
||||
afterward and is queued for rerun). Earlier13ports/14scenarios and115 source/lib
|
||||
tests passed; strict core Clippy preceded the last geometry/performance fixes.
|
||||
|
||||
1. Commit state evidence and fast-forward main from ad7feb5; coordinate Git index
|
||||
before carrying documentation into the active R6 checkout.
|
||||
Root41 server tests pass, including3 new 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.
|
||||
|
||||
Independent core review found association transition closure pulling unrelated
|
||||
types and missing empty-enum warning; both corrected and focused tests passed.
|
||||
Repeated per-ancestor full scans were simplified to one scan per helper call.
|
||||
Explicit debug inheritance timings250/500/1000:147/664/2739ms. Optimized timing is
|
||||
still required; no optimized performance claim yet.
|
||||
|
||||
Current ownership: drawing_correctness owns desktop except data_view.rs;
|
||||
state_architecture_review now owns only data_view.rs bounded focused-dictionary
|
||||
correction. Its independent review found unbounded inherited rows/picklists,
|
||||
unreachable recursive paths and loss of scenario values on same-phase style or
|
||||
same-exchange reselection. Drawing worker fixes recursive drill-down/draft retention.
|
||||
data_core now verifies Linux in a separate data-linux-review checkout/target.
|
||||
Root owns API/OpenAPI/reST, integration and native input. No concurrent file writers.
|
||||
|
||||
1. State evidence is committed and main fast-forwarded to a8f451e; DATA received
|
||||
the same evidence in c5276b1. Finish the3 concrete desktop review fixes and
|
||||
optimized inheritance measurement, then native data-authoring acceptance.
|
||||
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
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# R6 data and interface contract proposal
|
||||
|
||||
Implementation freeze (2026-09-06): `release-data-implementation.md` supersedes
|
||||
the earlier version-number and generic-port proposals below. Current contract is
|
||||
schema/source4 with explicit1/2/3 migration; existing typed PortContract remains
|
||||
authoritative. Value Record default `[]` is allowed at minimum0; Reference fields
|
||||
have no explicit default. See docs/language.rst4.5 for the implemented specification.
|
||||
|
||||
Status: read-only design, 2026-09-05. No implementation, test pass, or native Studio acceptance is claimed here. This is the recommended integration contract for the lead to freeze before the R6 worker changes exhaustive enums. It extends the current typed model and transaction path; it does not introduce an instance database, expression evaluator, units engine, or plugin metamodel.
|
||||
|
||||
## Evidence and scope
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# R6 implementation freeze — schema/source 4
|
||||
|
||||
Status: implementation starts in isolated D:/CodexBuilds/Capella2-data-integration.
|
||||
State editing acceptance stays on state-integration; merge its navigation fix later.
|
||||
Status: active implementation in isolated D:/CodexBuilds/Capella2-data-integration.
|
||||
State editing is accepted in main a8f451e; DATA includes its navigation fix and evidence.
|
||||
The full first-release goal remains incomplete.
|
||||
|
||||
## Outcome and contract
|
||||
|
||||
Reference in New Issue
Block a user