Checkpoint source 7 workflows and in-progress diagram authoring redesign
Rust checks / check (ubuntu-latest) (push) Canceled after 0s
Rust checks / check (windows-latest) (push) Canceled after 0s

Preserve current core, source, REST, desktop, recovery, documentation and validation work, including AGENTS.md and the development summary. This is a work-in-progress checkpoint: the new compact palette has outstanding compilation errors and native acceptance; earlier passing gates retain their documented scope.
This commit is contained in:
Codex
2026-09-10 10:06:55 -07:00
parent 4b6b5fc197
commit e2ecfea69b
162 changed files with 17595 additions and 926 deletions
+74 -2
View File
@@ -139,6 +139,13 @@ pub fn decode_with_report_limited(
}
let decoded = if bytes.iter().find(|b| !b.is_ascii_whitespace()) == Some(&b'{') {
let header: serde_json::Value = serde_json::from_slice(bytes)?;
if header
.get("schema_version")
.and_then(serde_json::Value::as_u64)
.is_some_and(|v| v <= 6)
{
reject_source7_fields(&header).map_err(FileError::Invalid)?;
}
if header
.get("schema_version")
.and_then(serde_json::Value::as_u64)
@@ -182,13 +189,14 @@ pub fn decode_with_report_limited(
Some(3) => v3::migrate(serde_json::from_slice(bytes)?, limits)?,
Some(4) => v4::migrate(serde_json::from_slice(bytes)?, limits)?,
Some(5) => migrate_v5(serde_json::from_slice(bytes)?, limits)?,
Some(6) => DecodeResult {
Some(6) => migrate_v6(serde_json::from_slice(bytes)?, limits)?,
Some(7) => DecodeResult {
project: serde_json::from_slice(bytes)?,
migration: None,
},
_ => {
return Err(FileError::Invalid(
"Unsupported or missing schema_version; expected 1, 2, 3, 4, 5 or 6.".into(),
"Unsupported or missing schema_version; expected 1, 2, 3, 4, 5, 6 or 7.".into(),
));
}
}
@@ -357,6 +365,70 @@ pub(crate) fn migrate_v5(
})
}
/// Reject explicit new fields before serde defaults can erase their presence.
/// This is also applied to source's resolved structured values.
pub(crate) fn reject_source7_fields(value: &serde_json::Value) -> Result<(), String> {
match value {
serde_json::Value::Object(fields) => {
if fields.contains_key("ContextualLink") {
return Err("ContextualLink requires schema/source 7.".into());
}
if fields.get("Relation").and_then(serde_json::Value::as_str) == Some("ContextualLink")
{
return Err("ContextualLink view selectors require schema/source 7.".into());
}
if fields.keys().any(|key| {
matches!(
key.as_str(),
"Operation"
| "ContextOwner"
| "ContextSource"
| "ContextTarget"
| "ContextPurpose"
)
}) {
return Err(
"Operation/contextual-link semantic facets require schema/source 7.".into(),
);
}
if fields
.get("Exchange")
.and_then(serde_json::Value::as_object)
.is_some_and(|body| body.contains_key("operation"))
{
return Err(
"Exchange.operation requires schema/source 7, including explicit null.".into(),
);
}
for nested in fields.values() {
reject_source7_fields(nested)?;
}
}
serde_json::Value::Array(values) => {
for nested in values {
reject_source7_fields(nested)?;
}
}
_ => {}
}
Ok(())
}
pub(crate) fn migrate_v6(
mut project: Project,
limits: crate::language::ParseLimits,
) -> Result<DecodeResult, FileError> {
if project.schema_version != 6 {
return Err(FileError::Invalid("Expected schema_version 6.".into()));
}
reject_source7_fields(&serde_json::to_value(&project)?).map_err(FileError::Invalid)?;
limits.check_model(&project).map_err(FileError::Limit)?;
project.schema_version = SCHEMA_VERSION;
Ok(DecodeResult {
project,
migration: Some(MigrationReport::data_upgrade(6)),
})
}
pub(crate) fn migrate_v1_with_report_limited(
old: v1::Project,
limits: crate::language::ParseLimits,