268 lines
17 KiB
Markdown
268 lines
17 KiB
Markdown
# R3 semantic review implementation freeze — schema/source 5
|
|
|
|
Status: production implementation authorized; not accepted or complete. Isolated
|
|
worktree `D:/CodexBuilds/Capella2-semantic-review`, branch `codex/semantic-review`,
|
|
base `ab661f2d332f540673ee0e2003b454c1765332bc`; dedicated target
|
|
`D:/CodexBuilds/Capella2-semantic-target`. R6 native work remains root-owned in DATA.
|
|
|
|
## Decision and evidence
|
|
|
|
Adopt C: a closed, typed, self-tagged review value per semantic facet. The
|
|
throwaway C proof is `b2ab2b1feb9b0ada03cd9d0974749bd7fd28c7f8` in the separate
|
|
transition-probe worktree. Its 11 passing tests comprise three B1 comparison
|
|
cases and eight C cases, including an independent adversarial review's concrete
|
|
counterexamples. Additional type/adapter code is accepted for fewer persisted
|
|
state invariants; this is not a claim that C uses fewer lines.
|
|
|
|
This supersedes the recursive `SemanticValue`/string-path recommendation in
|
|
release-transition-contract.md and the interim typed-carrier/mask/order-shadow
|
|
recommendation. Keep its engineering requirements: partial deliberate review,
|
|
explicit mapping, target-only preservation, honest unreviewed state, source/JSON
|
|
parity, and one stale-checked validated transaction. No generic metamodel, graph
|
|
synchronization service, runtime value tree, or second mutation engine is added.
|
|
|
|
Compiled core catalog: `semantic/types.rs` contains 84 scalar selectors across 13
|
|
families, nine reference collections, two ordered collections, and the closed
|
|
Literal/Annotation/Binding/Child/Incident/Artifact facts. The catalog coverage test
|
|
enumerates every current element payload, constructor branch and relation kind;
|
|
an unrepresented payload field fails that gate. Serialization paths used by the
|
|
private adapter are fixed implementation details, never accepted user selectors.
|
|
|
|
## Persisted shape and granularity
|
|
|
|
`TraceBaseline` retains existing `oa`/`sa: TracedProperties` and adds
|
|
`#[serde(default)] semantic: Option<SemanticBaseline>`. Old absence is Unreviewed;
|
|
never synthesize historical semantic values from today's project. Baseline and
|
|
Trace use PartialEq, because typed semantic values include finite f64.
|
|
|
|
`SemanticBaseline { facets: Vec<FacetReview> }` stores only independently reviewed
|
|
facts. `FacetReview` is a closed self-tagged enum, nested by actual model family;
|
|
each leaf carries `Reviewed<T> { oa: Observed<T>, sa: Observed<T> }`.
|
|
`Observed<T>` is `NotApplicable | Value(T)`. T is fixed by the enum variant, reusing
|
|
existing model types (DataValue, TypeRef, MessageValue, LifelineBinding, port/state
|
|
enums and artifact metadata). No entry means Unreviewed. `Value(None)` is a real
|
|
absent optional value, distinct from a missing constructor branch. Reject leaves
|
|
inapplicable on both sides and selectors outside the compared record family.
|
|
|
|
Historical keys use `KeyPair<K> { oa: Option<K>, sa: Option<K> }` in canonical
|
|
OA/SA coordinates. Annotation keys are the entire `(path, field)`; binding keys
|
|
are the referenced lifeline. An annotation or binding is one atomic optional row;
|
|
retargeting its key is explicit removal/addition, with no heuristic rename.
|
|
Other rows remain independently reviewable. Scalar field defaults are one atomic
|
|
optional vector because their repeated values have no stable identity.
|
|
|
|
Reference collection members and enum literals are individually reviewed facts.
|
|
Enum keys are exact case-sensitive strings, not list indexes. Source collection
|
|
Take applies additions/removals, preserving independently added target members.
|
|
Ordering is its own typed Vec<Id> fact; membership acknowledgement never refreshes
|
|
it. InterfaceItemAllocation order/protocols remain fields of the identified
|
|
relation, not a second writable Interface.items list.
|
|
|
|
Constructor groups are explicit, narrow semantic scopes. Data definition owns
|
|
its variant fields and coupled default; PortContract owns contract plus Legacy
|
|
payload; Event owns its variant payload; Occurrence owns its variant payload but
|
|
not common pre/postconditions. Nested MessageKind/Timer changes expose dependent
|
|
exchange/reply/value changes. StateKind is a semantic structural choice even
|
|
though it changes Element::kind(). Accept a discriminator switch and its whole
|
|
introduced/removed group atomically, retiring obsolete branch facts. Unchanged
|
|
kind cannot acknowledge unrelated bound/default drift by a Keep shortcut. An
|
|
explicit actual target switch may reconsider an earlier deliberate Keep.
|
|
|
|
Persist only `DataConstructor`, `PortConstructor`, `OccurrenceConstructor`,
|
|
`EventConstructor` and `MessageConstructor` discriminator enums (State uses the
|
|
existing StateKind). A grouped decision uses a transient typed record, retires
|
|
obsolete branch facts and stores each resulting descendant independently. A
|
|
constructor payload snapshot must never overlap later independently reviewed
|
|
leaves. Repeating Keep on an already acknowledged unequal discriminator pair
|
|
cannot acknowledge newly changed bounds/defaults. Constructor retirement writes
|
|
explicit NotApplicable target slots for agreement checking against other reviews.
|
|
|
|
Artifact reviews are attached facts of the owning semantic trace; they do not
|
|
widen ordinary Trace endpoint compatibility. Cover artifact membership and
|
|
name/description/owner/relation/URI/revision/fragment, preserving target-only links.
|
|
Do not fetch artifact content. Historical UUIDs remain after ordinary deletion,
|
|
and explicit identity remapping visits keys and typed values without treating
|
|
them as live graph edges.
|
|
|
|
## Complete field catalog
|
|
|
|
- Headers: existing name/description review; element parent. Identity, alias,
|
|
layer and placements are not incidental semantic edits.
|
|
- OA/SA primitive bodies have no payload; Process/FunctionalChain have step
|
|
membership/order. Shared Machine/Region have no own payload.
|
|
- ExchangeItem nature/mechanism/supertype; Interface supertype and independently
|
|
identified allocation relations.
|
|
- DataType constructor, integer/real bounds, string lengths, enum members,
|
|
Record supertype, default and unit. DataField TypeRef, multiplicity bounds,
|
|
unit, direction, storage and optional default vector.
|
|
- Port constructor, function input/output item membership, component
|
|
kind/orientation and Legacy direction/interface. Existing typed port generation,
|
|
explicit resolution/split and unsupported OA mappings remain authoritative.
|
|
- Scenario viewpoint/context/pre/postconditions/steps; Lifeline represented ref.
|
|
- Occurrence constructor/common pre/postconditions; Exchange endpoints/reference,
|
|
message kind/Timer expression, reply correlation and qualified annotations;
|
|
Action refs; Control kind; SequenceReference; ScenarioUse ref/bindings; State
|
|
refs; Fragment operator/branches; Branch guard/ordered occurrences.
|
|
- Event Signal item membership, Time kind/expression, Change expression; State
|
|
kind and entry/exit/do prose.
|
|
- All relation source/target endpoints; interface allocation order/protocols;
|
|
association roles/multiplicities/navigation; exchange item sets/ports/orientation;
|
|
capability-extend condition; sequence guard; state-transition kind, trigger/effect
|
|
sets and separate prose; StateAction phase. Other relation variants are endpoint-only.
|
|
- Direct owned-child membership, incident relation identity with endpoint role,
|
|
and attached artifact membership/properties. Rollups distinguish own drift from
|
|
linked impact; shared referenced definitions are not copied into every baseline.
|
|
|
|
## Review and command boundary
|
|
|
|
Use the existing transition selection/dependency/mapping planner and ordinary
|
|
Command preparation. Keep the prose request/API compatible; add sibling typed
|
|
semantic request/preview/apply helpers. Whole existing typed records may appear
|
|
as transient candidates or impact snapshots, never as persisted baseline carriers.
|
|
|
|
The implemented sibling boundary is `SemanticTransitionRequest { transition,
|
|
traces, references, reviews, candidates, accepted_impacts }`.
|
|
`traces` selects a particular trace by source UUID when one endpoint pair has
|
|
several traces; `references` is canonical OA→SA correspondence, including old
|
|
deleted IDs. `SemanticReviewRequest { source, resolutions, reset }` and
|
|
`FacetResolution { facet, decision }` use KeepTarget/TakeSource/Candidate.
|
|
Candidates are full existing typed Element/Relation/Artifact records with identity
|
|
and aliases protected; they must equal the result of selected facets exactly.
|
|
`plan_semantic_transition`, `prepare_semantic_transition` and
|
|
`apply_semantic_transition` reuse the existing mapping planner and Command batch.
|
|
Previews expose typed current/drift facts, acknowledged and retired selectors,
|
|
exact typed prepared impacts, conflicts, and a stale-check fingerprint.
|
|
|
|
Artifact metadata slots are keyed by the actual artifact UUID, independent of
|
|
which owning trace reaches them. Presence and owner share the ownership slot;
|
|
metadata selection requires the currently attached owner. An explicit Owner
|
|
candidate can move that link to another valid owner; its canonical owner slot
|
|
must agree with any selected attachment decision. Creating a link
|
|
requires a complete candidate and explicit review of every introduced metadata
|
|
field. Removing a link retires its metadata and checks those removed slots against
|
|
other decisions. Historical artifact keys/owners are visited only by explicit
|
|
identity remapping, alongside all other historical UUIDs.
|
|
|
|
Attachment authorization uses the immutable initial snapshot; metadata observations
|
|
use the identified artifact record. Thus a target-only Owner or Owner+Name candidate
|
|
records the actual resulting owner/metadata after a move, independent of facet
|
|
order. Presence remains relative to the trace owner. A subsequent metadata decision
|
|
through the former owner trace is rejected, while its historical observation remains
|
|
available for drift. This avoids replacing an explicit owner value with both-side NA.
|
|
|
|
Freeze mappings before proposals. Resolve all live and historical reference
|
|
members through explicit correspondence; no display-name matching. Many sources
|
|
may affect a target only when resolved deltas agree for each canonical target
|
|
slot. A source/key-pair collision or contradictory target delta is a conflict,
|
|
independent of request order. Mapping changes require explicit invalidation/reset
|
|
of affected old reviews; never silently replace or accumulate overlapping pairs.
|
|
|
|
An established paired selector remains the identity when one side's member or
|
|
constructor branch disappears. It suppresses the redundant generated one-sided
|
|
projection, preserving an NA/remaining-value observation. The reverse case is
|
|
different: a newly appearing pair does not suppress old one-sided history and
|
|
requires an explicit reset. Apply this rule to the closed keyed selector catalog,
|
|
not only enumeration or constructor special cases.
|
|
|
|
Every selected source derives desired values from the same immutable initial
|
|
project. Apply explicit baseline resets before deriving its current catalog or
|
|
constructor scope. Union all selected canonical slots across constructor scopes,
|
|
including introduced members and removals, and reject disagreement before applying
|
|
any writes. Materialize the agreed result once and compare every selected desired
|
|
slot against it, then repeat that audit after ordinary command preparation.
|
|
An exact approved cleanup impact still cannot contradict a selected Keep/Take.
|
|
This invariant replaces sequential proposal mutation and order-dependent audits.
|
|
When the target already has the proposed constructor, preserve target-only members
|
|
while reconciling its group; a source constructor change is not whole-list deletion
|
|
authority. Independently inferred orders must agree; commuting member removals
|
|
filter those orders to surviving members without refreshing order history.
|
|
|
|
Compare each side against its own reviewed value, retaining intentionally unequal
|
|
pairs. Keep acknowledges only the selected current source/retained target fact.
|
|
Take or a typed candidate acknowledges only the selected resulting fact. Untouched
|
|
changes remain drift. Preview unreviewed differences rather than falsely claiming
|
|
unchanged semantics. A selected constructor group names every fact it acknowledges.
|
|
|
|
New resolution admission requires the appropriate current record family and at
|
|
least one applicable current side. Persisted historical facts are different: their
|
|
typed former family/constructor and deleted UUIDs remain valid history even after
|
|
the live endpoints change. Validate their closed types, keys, duplicate slots,
|
|
finite values, text and work limits without requiring present-day live references
|
|
or present-day family applicability. Historical observations are never live edges.
|
|
|
|
Linked shared-definition drift is derived, not copied into each referring baseline.
|
|
The bounded walk follows reusable data fields/types, exchange items, interfaces,
|
|
events and interface allocation declarations, stopping at 4096 objects per side
|
|
or 32768 edges with an observable diagnostic. Parent edges and arbitrary architecture
|
|
neighborhoods do not expand that walk. Missing pairs/reviews remain Unreviewed;
|
|
own and linked rollups explicitly retain their unreviewed counts.
|
|
|
|
Preserve target-only members and records. Removing source membership proposes
|
|
unlinking, not deletion of target semantic objects. Ordered insertion is automatic
|
|
only with a unique unchanged mapped anchor; ambiguous insertion/reorder requires
|
|
an explicit final target order containing every surviving member once. Parent and
|
|
relation endpoint edits remain explicit canonical operations, with aggregate
|
|
membership effects linked to those same operations rather than competing commands.
|
|
|
|
Prepare one complete candidate, then compare the actual prepared project against
|
|
the explicitly reviewed result. Existing cleanup (including inherited annotation
|
|
pruning) can cause additional changes: expose their exact typed before/after
|
|
impact and require explicit review. Cancellation, stale fingerprint/ETag, missing
|
|
resolution or invalid candidate leaves model, baseline, revision/history and disk
|
|
unchanged. Baseline updates join the same ordinary atomic transaction. Repeated
|
|
application is idempotent. The plan is still a client candidate, not a security
|
|
receipt; ordinary validation is never bypassed.
|
|
|
|
## Source/schema handoff and ownership
|
|
|
|
Core owns model/types, the closed semantic catalog/helpers, transition integration,
|
|
reference/remap/admission validation, lib registration and semantic core tests.
|
|
Source worker owns persistence.rs version dispatch, language/source_project/source
|
|
files, V4 compatibility migration and source/migration tests. Desktop/server are
|
|
later separate integrations. Communicate compiled public types before dependent
|
|
source edits. Coordinate the dedicated target; no concurrent Cargo mutations.
|
|
|
|
Agreed internal helper, rooted at SemanticBaseline's serde tree:
|
|
|
|
```rust
|
|
pub(crate) enum HistoricalSourceKind { Reference, Enum }
|
|
pub(crate) fn historical_source_slots(
|
|
baseline: &SemanticBaseline,
|
|
) -> Vec<(Vec<String>, HistoricalSourceKind)>;
|
|
```
|
|
|
|
Paths are internal field names/list indexes, never persisted or public SemanticPath.
|
|
Core derives slots from the same finite typed leaf catalog, including nested Id,
|
|
model enums, Option/Vec, annotations/bindings and NotApplicable observations.
|
|
Source can normalize historical AST leaves to temporary JSON, deserialize the
|
|
existing typed SemanticBaseline, then check original token classes with this map.
|
|
References require an explicit historical `uuid "..."`; enum leaves require bare
|
|
words; other string leaves require quotes. Historical @alias is rejected. This
|
|
handles Reviewed oa/sa text fields without weakening existing live @alias rules.
|
|
Formatting and token/comment identity use the same slot metadata.
|
|
|
|
Schema/source5 is explicit. V4 migration freezes only changed Trace/TraceBaseline
|
|
shapes plus the closed old constructor catalog, reusing unchanged typed model
|
|
records; retain V1/V2/V3 adapters and real compatibility fixtures. No public
|
|
intermediate5 acceptance before full catalog, baseline roundtrip, source/JSON/API
|
|
agreement and coupled persistence are verified. Earlier source/data4 remains real
|
|
compatibility input, not a silently mutable contract.
|
|
|
|
## Verification gates
|
|
|
|
First close pure types/catalog/drift and typed source admission, then mapped review
|
|
and complete atomic preparation. Cover every listed field family with observed
|
|
mutations, including both directions and same-kind counterparts. Required focused
|
|
cases: partial Keep/Take; constructors/defaults/units; row identity and changed old
|
|
deleted references; target-only fields/triggers/literals/bindings/artifacts; order
|
|
ambiguity; mapping reset and agreeing/conflicting many-to-one slots; wrong-family
|
|
and both-side-NA admission; old semantic absence; prepared cleanup impacts; stale
|
|
plan; duplicate decisions; no-op acknowledgement; repeat apply; undo/redo and invalid
|
|
rollback. Test finite bounds and bounded nested/historical reference work.
|
|
|
|
Then source/JSON historical UUID and mixed-constructor roundtrip, explicit migration,
|
|
comment/identity preservation, actual REST ETag/disk/restart, native compact/normal
|
|
review UI, independent semantics/correctness review and Windows/Linux verification.
|
|
Do not quietly reduce this to scalar-only reconciliation. Incremental commits are
|
|
implementation checkpoints, not release acceptance.
|