46 lines
13 KiB
Markdown
46 lines
13 KiB
Markdown
# Scenario / analysis schema8 integration audit
|
|
|
|
**Decision boundary:** optional Scenario presentation can share the pending schema8 model, but `aed07176` is not a version-adoption patch. Four integration obligations remain: old-schema field-presence rejection, combined resource accounting, atomic composition of reference preflights, and preservation of typed source-update contexts. They are root codec/integration work, not defects claimed against the peer's explicitly isolated contribution. Do not implement them in the frozen S2 worktree before the typed-adapter phase handoff.
|
|
|
|
Inspected exact Scenario source `aed07176ab453b981d5f9c76e504c531f6dd7f42` and clean analysis worktree `6216cff4cfeb1502b8453b40547aacb74941f2b2`. The Scenario object was missing locally; a scoped `git fetch --no-tags --no-write-fetch-head gitea <exact SHA>` populated objects without changing the root checkout/branch or frozen worktree. [Input manifest](scenario-analysis-version-integration-inputs-20260913.json), SHA256 `c72d6d140579dcbf910f81505ced83a3cd6fa09bae813469be59da635033cbb2`, pins 22 actual source blobs. Accepted r2 typed-definition grammar was read from the analysis worktree's `harness/analysis-source8-20260913/analysis-source8-repair-design-r2-20260913.md`.
|
|
|
|
Read Gitea #7 through [843](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/7#issuecomment-843), #20 through [845](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/issues/20#issuecomment-845), and the [published aed gate README at e7ceff11](http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio/src/commit/e7ceff11afb85f5e944fa3a818acc04e464af2d3/harness/experiments/scenario-core-gates-20260913/README.md). It records 26 focused cases overlapping 471 executed core passes, one ignored probe, strict pass and preserved earlier failures. This audit did not rerun/independently validate those receipts. A newer renderer candidate68a81c3 is reported in845, but its source/runtime is outside this aed codec audit. No gesture/rendering import is proposed.
|
|
|
|
## Exact seams and mandatory failure cases
|
|
|
|
**1. Freeze old Diagram contracts before adopting the new current field.** Peer `model.rs:1523` adds `layout: Option<DiagramLayout>` with serde-default None and omitted serialization of None. `scenario_layout.rs:10-35` defines Scenario payload, lane rows and message rows; message addresses retain explicit reference paths. None and Some(empty) intentionally differ. Analysis is schema8; the peer stays schema7 experimentally. Keep root's version decision; do not import the peer's SCHEMA_VERSION=7 over analysis.
|
|
|
|
Analysis `migration_v7.rs:10-25` freezes only the top-level Project envelope and reuses current Diagram. `migration_v3/mod.rs:23` and `migration_v4.rs:59` also share Diagram. Adding a current field therefore makes typed older envelopes accept it unless separately rejected. Existing `persistence.rs:163-166` inspects raw JSON only for versions<=6, and `check_legacy_header:225` catches unknown Diagram fields only for pre6. Neither protects schema7; schema6 also lacks a layout-presence check. The actual JSON boundary has no version-aware nested Diagram visitor: json_codec.rs:276-297 delegates current decoding to Project::deserialize and legacy decoding to generic serde_json::from_slice::<T>; the derived current Diagram accepts its newly known layout field even when the frozen top-level DTO denies unknown fields. `reject_pre8_project:479` currently checks definitions/analysis kinds only. Testing `layout.is_some()` after serde is inadequate: explicit old `layout:null` has already become None.
|
|
|
|
Minimal compatible repair: a context-specific raw Diagram-field presence rejection (at diagrams.<id>.layout, not a recursive blacklist for every key named layout) for schemas<8 before deserializing current Diagram, and a corresponding source check in `language.rs:1757` **before** defaults/merge/from_value. Reject explicit `layout` even null/none/empty payload. Do not simply extend the existing call to `check_legacy_header` to version7: it unconditionally invokes `reject_source7_fields`, which would wrongly reject legitimate schema7 Operation/contextual-link fields. Keep the <=6 source7 restriction separate from the new <=7 layout restriction. Frozen nested Diagram DTOs are a stronger alternative, but require more migration adapters; either approach must retain old field-presence semantics.
|
|
|
|
Also protect typed internal migration entrances: `reject_pre8_project` should reject any non-None current layout, and `language/source3_bridge.rs:13-47` must not blindly forward a scratch Diagram carrying a new payload. Its exhaustive Project destructure does not detect additions inside the shared Diagram type. Never strip a supplied payload or serialize a current record back into an older contract as a workaround.
|
|
|
|
Required public negative matrix: real legal schema3/4/5/6/7 projects with one diagram, inject `layout:null`, empty Scenario, and nonempty Scenario; all reject without writes. Source6/7 `layout none;` and `layout { Scenario { lanes []; messages []; }; };` must reject, including included modules. Keep legal schema7 Operation/contextual-link positives to catch overbroad rejection. Legitimate old payloads without layout migrate to current None and an empty analysis catalog, with exact semantic IDs/geometry retained. Current schema8 absent/None/Some(empty)/sparse layout round trips must preserve their intended distinctions. Standalone `serde_json::<Diagram>` success is not public version admission.
|
|
|
|
**2. Wire both semantic row and ordered-reference accounting.** Peer `scenario_layout.rs:61` deliberately exposes only a contribution: `None=0`, `Some=1 + lanes.len + messages.len`, no graph objects. Its `reference_visitor_and_record_count_cover_explicit_rows` test proves 0 and3 for one lane/one message, not integration into public limits. Analysis `language.rs:62-108` currently counts graph+definitions, ordinary diagrams/nodes/routes/anchors and `analysis::nested_record_count`, but never Scenario payloads. Add every diagram's contribution using bounded/saturating accumulation; do not replace the existing analysis contribution or count only the active view. Hidden/filtered/inactive diagrams and structurally invalid or disabled-looking payloads still consume stored-record/reference budgets; visibility and renderer support are not admission exemptions.
|
|
|
|
The variable-length `message.address.references` is a separate ordered-reference budget hook. Count its actual length across **all** rows/diagrams together with existing element steps and ContextualLink endpoint paths, including malformed/unsupported candidates. Peer `scenario_layout.rs:226` rejects nonempty paths semantically, but that is not a resource meter. It still receives already allocated vectors. Lane/occurrence singleton references are bounded by row counts; this does not require redefining the existing budget as every global reference.
|
|
|
|
Retain JSON physical preflight (`persistence/json_codec.rs:87`, byte/token/aggregate-entry/container/string ceilings) before serde and final `ParseLimits::check_model` before structural validation (`persistence.rs:213`). Source `language.rs:1544` and bundle `source_project.rs:503` currently meter declaration counts, not these nested rows. The root typed-source resource phase must charge layout rows/reference entries under the **same whole-document/bundle** budget before potentially large collection/resolution work; do not reset per included file, diagram or list and do not route Scenario coordinates through Exact/analysis-expression node accounting. Do not turn on DEPTH_128_VALIDATED (`json_codec.rs:22`) for this shallow optional payload.
|
|
|
|
Minimal failures: budget B accepts exact combined ordinary+analysis+Scenario count, B-1 rejects; two views in different includes exceed a shared limit though each fits; Some(empty) consumes its payload record; a single rejected message with an oversized explicit reference path is charged; existing ContextualLink paths plus Scenario paths share the ordered-reference ceiling. Exercise public JSON/source and programmatic Session/prepare boundaries, with a no-mutation sentinel. Physical preflight alone does not prove the configured semantic max_records limit.
|
|
|
|
**3. Compose both fallible remap domains before any identity/reference mutation.** Peer `references.rs:207-323` adds diagram visitors, Scenario projection owner remapping and affected-row collision preflight; `session.rs:917` runs it before reidentifying. Analysis already has a different preflight at `references.rs:214-217` and `session.rs:941`, plus `analysis::references::remap_project`, definitions and scoped ParameterIds. A blind replacement would lose one domain. Worse, adding peer checks only inside the final remap call lets root `session::reidentify` change object identity before a Scenario collision rejects.
|
|
|
|
Use one composed check entry point called before mutation by both public `references::remap_references` and `session::reidentify`; it must run analysis key/call-map checks and Scenario lane/address collision checks first. Then retain typed analysis remapping and peer diagram visitor/deletion pruning, including Scenario owner-view cascade. Parameter IDs remain scoped: a ParameterId equal to the remapped global UUID must not be rewritten merely by equality. Preserve the peer's repair-batch tolerance: unrelated already-invalid duplicate rows do not become a new global admission requirement for an unaffected remap.
|
|
|
|
Required union negatives/positives: direct public remap and Reidentify each leave the complete Project unchanged on a Scenario lane/message collision; analysis override/call-argument collision remains atomic with Scenario present; successful remap updates layout/Scenario owner/global analysis subject refs while preserving equal-valued scoped ParameterIds; delete only the actual closure, retaining unrelated view overrides and incomplete-message positions. These are additional union tests, not a replacement for the peer's26 cases or root analysis tests.
|
|
|
|
**4. Preserve source8 typed field dispatch and peer row provenance.** Peer `source_project.rs:1136-1154` adds explicit EditContext path `Diagram -> layout -> Scenario -> lanes/messages`; `:1544-1594` uses lifeline identity or full occurrence-address identity only in that context. This must compose with the root's future typed definition/parameter/call-site/override paths, not become a generic field-name heuristic. A calculation parameter or ordinary record named `messages`, `lanes`, `layout`, etc. must not acquire Scenario row identity. Diagram coordinates remain the existing finite f32 numeric grammar; new analysis literals/operators must not silently broaden it to expressions/ratios.
|
|
|
|
Retain context arguments at both update entry (`peer source_project.rs:934`) and migration entry (`peer source_project/source_migration.rs:72`); the first omitted migration argument caused a real retained compile failure. Keep the peer's authored `layout none` preservation rule (`source_project.rs:1346`) for an unrelated edit, while a real Some->None clear removes payload syntax. Retain current `SourceIndex` declaration/top-level field meanings and the root's distinct Definition record category; no Scenario data should be classified as a new global definition or graph object.
|
|
|
|
Reuse peer `scenario_layout/tests/source_lifecycle.rs` controls for reordered rows with identity-following comments, untouched 4.20e2/2.00e2 spellings, alias changes, identity swaps, one-Undo command batches, explicit none, clear, invalid-source nonmutation and unchanged file ownership. Add one mixed schema8 bundle with neutral definitions + analysis Expr/call parameters + Scenario layout: alias/parameter rename affects only typed uses, row reordering leaves analysis source byte-exact, analysis edits leave layout/comment/number spelling byte-exact, and full Project equals recompiled source. Old source migration must retain includes/trivia, never synthesize authored layout; current canonical/source updates must publicly reopen exactly before checked save may stage/replace.
|
|
|
|
## Ownership / order
|
|
|
|
Root owns public version8 adoption, older wire/source rejection, shared counts/resource policy, source8 typed-adapter composition and save-before-replace safety. The peer owns `scenario_layout` semantics, sparse commands, scoped source-row provenance and renderer/gesture progress. Import reviewed peer mechanisms after the S2 declaration/lowering boundaries stabilize; compose shared `model/language/source_project/references/session/persistence` changes deliberately. No change to peer gesture policy, automatic fallback policy, activation rendering or new schema number is needed for these codec hooks.
|
|
|
|
The original checked-save regression must remain red until public source8 is complete; keep the S0 public-decode/full-equality guard. Peer source7 experimental tests should be ported to the final current schema fixtures at integration, while explicit old-schema layout tests remain negative. Passing either isolated suite does not waive combined admission, native or API lifecycle gates. This audit changed no production source, ran no compiler/GUI and posted nothing to Gitea.
|