Skip to content

Add variant support to FwLite (backend + viewer UI)#2410

Closed
myieye wants to merge 21 commits into
developfrom
feat/variants-ui
Closed

Add variant support to FwLite (backend + viewer UI)#2410
myieye wants to merge 21 commits into
developfrom
feat/variants-ui

Conversation

@myieye

@myieye myieye commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Cumulative PR for the variants feature — the backend step reviewed to green in #2408 (CodeRabbit handled, Devin clean, CI green), the viewer UI, plus post-#2408 hardening that still needs human eyes: 0d03aed28 aligns cycle detection with liblcm's exact AllComponents semantics and changes replay behavior of the shipped AddEntryComponentChange (justification: VARIANTS.md decision 7; skew story: VARIANTS.md rollout notes), along with 3b05ad8c1/5d6b0c050 (validator tests, docs) and follow-up test hardening. Part of an iterative review workflow; steps get merged one by one once everything is reviewed.

Backend (#2408 + the commits above): one MiniLcm Variant link = one FieldWorks LexEntryRef (RefType=Variant) target pair with per-link Types/HideMinorEntry/Comment for lossless FLEx round-trip; VariantType as a first-class synced object; cycle guard mirrors liblcm's combined complex-form+variant acyclicity including its sense-target no-recurse rule; per-link edits split FLEx's shared multi-target refs before mutating; flattened type reads expose the Irregularly Inflected Form subtypes (forum thread); Sena-3 verified data regenerated. Full design log: backend/FwLite/VARIANTS.md.

UI: "Variant of" and "Variants" entry-editor fields with a per-link "Variant type" checkbox menu; new links default to Unspecified Variant like FLEx; demo project seeded; Playwright covers both directions plus the type toggle. HideMinorEntry/Comment are synced but deliberately have no editor UI yet.

Tests: conformance suites on both IMiniLcmApi implementations, including a seeded random-graph differential test against a port of LCM's AllComponents oracle, and targeted mutation checks that the new cycle/shared-ref tests actually kill faults.

Rollout: new Harmony change types — deploy FwHeadless before/with a client release that writes variants. The AddEntryComponentChange semantics change rides along on any deploy and affects complex-form projects during version skew (rare shape, converges on auto-update — see VARIANTS.md rollout notes). Known gap: pre-existing FwLite-only projects have no variant types seeded, so their new links are untyped (follow-up).

🤖 Generated with Claude Code

myieye and others added 12 commits July 4, 2026 15:37
One Variant link = one LexEntryRef (RefType=Variant) with per-link Types,
HideMinorEntry and Comment (LCM Summary), per VARIANTS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Conformance suites for both IMiniLcmApi implementations, change/usage/serialization
tests, verified-file regens, AutoFaker support. LCM enforces acyclicity over the
combined complex-form + variant graph, so AddVariantChange mirrors that check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerated via ProjectTemplateTests.GenerateTemplate; new CRDT projects get the
7 standard FLEx variant types (well-known guids), matching FieldWorks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Variant lists sort by composite key on both sides (deterministic, culture-free);
BulkCreateEntries emits variant links; regenerated Sena3 live db + snapshots —
sena-3's real variants (custom Pronunciation Variant type) now round-trip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A sense-targeted variant link is identified by its full composite key; the FwData
bridge matched by sense guid alone, so a moved sense made the sync drop the link
(new regression test covers both implementations).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…riant entry id

Both implementations now reject a MainSenseId that belongs to a different entry
(fail before mutation); EntryValidator requires VariantEntryId on Variants items.
Also corrects the stale cycle-guard decision text in VARIANTS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Variant of / Variants entry fields with per-link variant-type menu, demo data
seed, i18n strings, Playwright coverage. New variants default to Unspecified
Variant like FLEx.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 832a2d6d-3628-44b7-8ed8-3e0a85992596

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Variant and VariantType support across backend, sync, FwData bridge, frontend, demo data, and tests. The PR introduces new models and APIs, persists and syncs variant links and types, exposes them in the viewer, and updates snapshots, fixtures, and localization.

Changes

Variant Support

Layer / File(s) Summary
Models and API contracts
backend/FwLite/MiniLcm/Models/*, backend/FwLite/MiniLcm/IMiniLcm*.cs, backend/FwLite/MiniLcm/CreateEntryOptions.cs, backend/FwLite/MiniLcm/ProjectSnapshot.cs, backend/FwLite/LcmCrdt/Changes/CreateVariantType.cs
Adds Variant/VariantType records, extends Entry, ProjectSnapshot, and read/write contracts, and adds the new create-type change.
Validation rules
backend/FwLite/MiniLcm/Validators/*, backend/FwLite/MiniLcm.Tests/Validators/*
Adds validators for Variant and VariantType, wires them into DI and wrappers, and expands validation tests.
CRDT changes
backend/FwLite/LcmCrdt/Changes/*, backend/FwLite/LcmCrdt.Tests/Changes/*
Adds variant change types, cycle detection, and tests for link creation, deletion, and type management.
CRDT storage, migrations, and API
backend/FwLite/LcmCrdt/*, backend/FwLite/LcmCrdt.Tests/Data*, backend/FwLite/LcmCrdt.Tests/DataModelSnapshotTests.*, backend/FwLite/LcmCrdt/Templates/*
Adds storage mappings, repository queries, migrations, snapshot updates, and API endpoints for variant data.
FwData bridge
backend/FwLite/FwDataMiniLcmBridge/*, backend/FwLite/LfClassicData/*, backend/FwLite/FwDataMiniLcmBridge.Tests/*
Maps FLEx variant refs to MiniLcm models and adds update proxies and behavior tests.
Sync and API wiring
backend/FwLite/MiniLcm/SyncHelpers/*, backend/FwLite/FwLiteProjectSync/*, backend/FwLite/FwLiteShared/Services/*, backend/FwLite/FwLiteWeb/Hubs/*, related tests
Wires variant sync through project sync, wrappers, JS interop, SignalR, dry-run, and normalization layers.
Frontend UI
frontend/viewer/src/lib/*, frontend/viewer/src/project/*, frontend/viewer/tests/*, frontend/viewer/src/stories/*
Adds viewer types, editor components, demo hooks, and E2E coverage for variant editing.
Localization
frontend/viewer/src/locales/*.po
Adds and re-sources variant-related labels across locale catalogs.
Design doc
backend/FwLite/VARIANTS.md
Documents the variant support design and rollout plan.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: 💻 FW Lite

Suggested reviewers: hahn-kev

Poem

A rabbit hops through variant fields,
Where links and types and sync unite;
🐇 One hop for FwData, one for CRDT,
And one for editors glowing bright.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding variant support across backend and viewer UI.
Description check ✅ Passed The description is detailed and directly matches the changeset, covering backend, UI, tests, and rollout notes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/variants-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@argos-ci

argos-ci Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Awaiting the start of a new Argos build…

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
frontend/viewer/src/lib/entry-editor/field-editors/VariantTypesMenuItems.svelte (1)

19-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Mutating variant prop directly instead of using a callback/bindable.

toggleType reassigns variant.types on the passed-in prop object rather than emitting the new value; it relies on the caller reassigning the outer array to force re-render (see the workaround comments in VariantOf.svelte/Variants.svelte). Consider making variant $bindable() or returning the updated types via onchange to make the data flow explicit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/viewer/src/lib/entry-editor/field-editors/VariantTypesMenuItems.svelte`
around lines 19 - 32, The `toggleType` handler in `VariantTypesMenuItems.svelte`
is mutating the passed-in `variant` prop directly by reassigning
`variant.types`, which makes the data flow implicit and depends on parent-side
rerenders. Update the component to use an explicit binding/callback pattern
instead: make `variant` bindable or have `toggleType` emit the updated types
through `onchange` so the parent owns the state update. Keep the existing
`hasType` and `toggleType` symbols as the main places to adjust the flow.
frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte (1)

1-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate logic with Variants.svelte.

VariantOf.svelte and Variants.svelte share almost identical structure (props shape, addVariant* construction, disableEntry/disableSense), differing only in which side (mainEntryId/variantEntryId) is fixed to the current entry. Consider extracting a shared parameterized component/composable to avoid drift between the two as future changes land.
[medium]

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte` around
lines 1 - 62, `VariantOf.svelte` duplicates nearly the same props,
`addVariantOf`, `disableEntry`, and `disableSense` logic found in
`Variants.svelte`; refactor this into a shared parameterized component or
composable so the only difference is which side of the relationship is anchored
to the current entry. Keep the existing behavior in `addVariantOf`,
`disableEntry`, and `disableSense`, but move the common `IVariant` construction
and entry/sense disabling rules into reusable logic to prevent future drift
between the two editors.
backend/FwLite/MiniLcm.Tests/AutoFakerHelpers/EntryFakerHelper.cs (1)

145-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

MainSenseId is always nulled — sense-scoped variant links are never exercised by this fixture.

The analogous CreateComplexFormComponentEntry helper actually creates a matching Sense on the linked entry when ComponentSenseId is set, so that scenario is exercised in tests. CreateVariantLinkEntry instead unconditionally nulls MainSenseId, meaning any test relying on this shared faker helper (e.g. VariantTests.cs, VariantSyncTests.cs, VariantTestsBase.cs) will never generate/roundtrip a variant that targets a specific main-entry sense.

Consider mirroring the complex-form-component pattern: when MainSenseId is set, create a matching Sense on the created main entry instead of always clearing it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/FwLite/MiniLcm.Tests/AutoFakerHelpers/EntryFakerHelper.cs` around
lines 145 - 190, `CreateVariantLinkEntry` is clearing `MainSenseId`
unconditionally, so sense-scoped variant links are never created in this faker.
Update the helper to mirror `CreateComplexFormComponentEntry`: when a variant
has `MainSenseId` set, create or attach a matching `Sense` on the linked main
entry before creating the entry, and only null it when no sense target exists.
Keep the fix localized in `CreateVariantLinkEntry` so tests using this shared
helper can exercise and roundtrip sense-specific variant links.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/FwLite/LcmCrdt/LcmCrdtKernel.cs`:
- Around line 328-353: Refresh embedded variant type copies when a VariantType
is renamed, because JsonPatchChange<VariantType> currently updates only the
canonical record while Variant.Types JSONB snapshots remain stale. Update the
rename flow in the VariantType handling path so that, after changing the type
name, any Variant rows referencing it are rewritten and their Types payload
reserialized with the new Name; use the VariantType and Variant
mapping/configuration in LcmCrdtKernel to locate the affected entities.

In `@backend/FwLite/VARIANTS.md`:
- Around line 85-98: The Variant sketch’s Comment field is modeled too loosely
compared with the implementation in Variant.cs. Update the Variant record
definition in VARIANTS.md to match the actual model by making Comment
non-nullable RichMultiString and reflecting that it has a default instance, so
the sketch no longer implies unnecessary null handling.

In `@frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte`:
- Around line 50-61: The VariantOf.svelte picker currently blocks only direct
reverse variant links in disableEntry/disableSense, but it still allows
selections that create a cycle through an existing complex-form relationship.
Update the selection guards in disableEntry and disableSense to also reject any
entry/sense that would introduce a mixed complex-form cycle, using the existing
entry.variantOf and entry.variants checks as the starting point and extending
them to cover indirect cyclic paths before the user can select them.

---

Nitpick comments:
In `@backend/FwLite/MiniLcm.Tests/AutoFakerHelpers/EntryFakerHelper.cs`:
- Around line 145-190: `CreateVariantLinkEntry` is clearing `MainSenseId`
unconditionally, so sense-scoped variant links are never created in this faker.
Update the helper to mirror `CreateComplexFormComponentEntry`: when a variant
has `MainSenseId` set, create or attach a matching `Sense` on the linked main
entry before creating the entry, and only null it when no sense target exists.
Keep the fix localized in `CreateVariantLinkEntry` so tests using this shared
helper can exercise and roundtrip sense-specific variant links.

In `@frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte`:
- Around line 1-62: `VariantOf.svelte` duplicates nearly the same props,
`addVariantOf`, `disableEntry`, and `disableSense` logic found in
`Variants.svelte`; refactor this into a shared parameterized component or
composable so the only difference is which side of the relationship is anchored
to the current entry. Keep the existing behavior in `addVariantOf`,
`disableEntry`, and `disableSense`, but move the common `IVariant` construction
and entry/sense disabling rules into reusable logic to prevent future drift
between the two editors.

In
`@frontend/viewer/src/lib/entry-editor/field-editors/VariantTypesMenuItems.svelte`:
- Around line 19-32: The `toggleType` handler in `VariantTypesMenuItems.svelte`
is mutating the passed-in `variant` prop directly by reassigning
`variant.types`, which makes the data flow implicit and depends on parent-side
rerenders. Update the component to use an explicit binding/callback pattern
instead: make `variant` bindable or have `toggleType` emit the updated types
through `onchange` so the parent owns the state update. Keep the existing
`hasType` and `toggleType` symbols as the main places to adjust the flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cb9b7020-0708-4d77-b731-0b165799ebba

📥 Commits

Reviewing files that changed from the base of the PR and between a9cf4ca and 3517b56.

📒 Files selected for processing (103)
  • backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/VariantTests.cs
  • backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs
  • backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateVariantProxy.cs
  • backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateVariantTypeProxy.cs
  • backend/FwLite/FwLiteProjectSync.Tests/EntrySyncTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/Import/ResumableTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/Snapshots/sena-3_snapshot.2026-06-18.verified.txt
  • backend/FwLite/FwLiteProjectSync.Tests/SyncTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/UpdateDiffTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/VariantSyncTests.cs
  • backend/FwLite/FwLiteProjectSync.Tests/sena-3-live.verified.sqlite
  • backend/FwLite/FwLiteProjectSync.Tests/sena-3-live_snapshot.verified.txt
  • backend/FwLite/FwLiteProjectSync/CrdtFwdataProjectSyncService.cs
  • backend/FwLite/FwLiteProjectSync/DryRunMiniLcmApi.cs
  • backend/FwLite/FwLiteProjectSync/Import/ResumableImportApi.cs
  • backend/FwLite/FwLiteShared/Services/MiniLcmApiNotifyWrapper.cs
  • backend/FwLite/FwLiteShared/Services/MiniLcmJsInvokable.cs
  • backend/FwLite/FwLiteWeb/Hubs/MiniLcmApiHubBase.cs
  • backend/FwLite/LcmCrdt.Tests/Changes/ChangeDeserializationRegressionData.latest.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Changes/UseChangesTests.cs
  • backend/FwLite/LcmCrdt.Tests/Changes/VariantChangeTests.cs
  • backend/FwLite/LcmCrdt.Tests/Data/MigrationTests.cs
  • backend/FwLite/LcmCrdt.Tests/Data/MigrationTests_FromScriptedDb.v1.ProjectSnapshot.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/MigrationTests_FromScriptedDb.v1.Snapshots.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/MigrationTests_FromScriptedDb.v2.ProjectSnapshot.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/MigrationTests_FromScriptedDb.v2.Snapshots.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/SnapshotDeserializationRegressionData.latest.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/SnapshotDeserializationRegressionData.legacy.verified.txt
  • backend/FwLite/LcmCrdt.Tests/Data/VerifyRegeneratedSnapshotsAfterMigrationFromScriptedDb.v1.verified.json
  • backend/FwLite/LcmCrdt.Tests/Data/VerifyRegeneratedSnapshotsAfterMigrationFromScriptedDb.v2.verified.json
  • backend/FwLite/LcmCrdt.Tests/DataModelSnapshotTests.VerifyChangeModels.verified.txt
  • backend/FwLite/LcmCrdt.Tests/DataModelSnapshotTests.VerifyDbModel.verified.txt
  • backend/FwLite/LcmCrdt.Tests/DataModelSnapshotTests.VerifyIObjectWithIdModels.verified.txt
  • backend/FwLite/LcmCrdt.Tests/MiniLcmTests/VariantTests.cs
  • backend/FwLite/LcmCrdt.Tests/SnapshotAtCommitServiceTests.cs
  • backend/FwLite/LcmCrdt/Changes/CreateVariantType.cs
  • backend/FwLite/LcmCrdt/Changes/Entries/AddVariantChange.cs
  • backend/FwLite/LcmCrdt/Changes/Entries/AddVariantTypeChange.cs
  • backend/FwLite/LcmCrdt/Changes/Entries/RemoveVariantTypeChange.cs
  • backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs
  • backend/FwLite/LcmCrdt/Data/EntryQueryHelpers.cs
  • backend/FwLite/LcmCrdt/Data/MiniLcmRepository.cs
  • backend/FwLite/LcmCrdt/LcmCrdtDbContext.cs
  • backend/FwLite/LcmCrdt/LcmCrdtKernel.cs
  • backend/FwLite/LcmCrdt/Migrations/20260703134525_AddVariants.Designer.cs
  • backend/FwLite/LcmCrdt/Migrations/20260703134525_AddVariants.cs
  • backend/FwLite/LcmCrdt/Migrations/LcmCrdtDbContextModelSnapshot.cs
  • backend/FwLite/LcmCrdt/QueryHelpers.cs
  • backend/FwLite/LcmCrdt/Templates/blank-project-template.json
  • backend/FwLite/MiniLcm.Tests/AutoFakerHelpers/EntryFakerHelper.cs
  • backend/FwLite/MiniLcm.Tests/FluentAssertGlobalConfig.cs
  • backend/FwLite/MiniLcm.Tests/Validators/VariantTypeValidationTests.cs
  • backend/FwLite/MiniLcm.Tests/Validators/VariantValidationTests.cs
  • backend/FwLite/MiniLcm.Tests/VariantTestsBase.cs
  • backend/FwLite/MiniLcm/CreateEntryOptions.cs
  • backend/FwLite/MiniLcm/IMiniLcmReadApi.cs
  • backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs
  • backend/FwLite/MiniLcm/Import/ProjectImporter.cs
  • backend/FwLite/MiniLcm/MiniLcmApiExtensions.cs
  • backend/FwLite/MiniLcm/Models/Entry.cs
  • backend/FwLite/MiniLcm/Models/IObjectWithId.cs
  • backend/FwLite/MiniLcm/Models/Variant.cs
  • backend/FwLite/MiniLcm/Models/VariantType.cs
  • backend/FwLite/MiniLcm/Normalization/MiniLcmApiWriteNormalizationWrapper.cs
  • backend/FwLite/MiniLcm/ProjectSnapshot.cs
  • backend/FwLite/MiniLcm/SyncHelpers/EntrySync.cs
  • backend/FwLite/MiniLcm/SyncHelpers/VariantSync.cs
  • backend/FwLite/MiniLcm/SyncHelpers/VariantTypeSync.cs
  • backend/FwLite/MiniLcm/Validators/EntryValidator.cs
  • backend/FwLite/MiniLcm/Validators/MiniLcmApiValidationWrapper.cs
  • backend/FwLite/MiniLcm/Validators/MiniLcmValidators.cs
  • backend/FwLite/MiniLcm/Validators/VariantTypeValidator.cs
  • backend/FwLite/MiniLcm/Validators/VariantValidator.cs
  • backend/FwLite/VARIANTS.md
  • backend/LfClassicData/LfClassicMiniLcmApi.cs
  • frontend/viewer/src/lib/dotnet-types/generated-types/FwLiteShared/Services/IMiniLcmJsInvokable.ts
  • frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IEntry.ts
  • frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IVariant.ts
  • frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IVariantType.ts
  • frontend/viewer/src/lib/dotnet-types/index.ts
  • frontend/viewer/src/lib/entry-editor/EntryOrSenseItemList.svelte
  • frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte
  • frontend/viewer/src/lib/entry-editor/field-editors/VariantTypesMenuItems.svelte
  • frontend/viewer/src/lib/entry-editor/field-editors/Variants.svelte
  • frontend/viewer/src/lib/entry-editor/object-editors/EntryEditorPrimitive.svelte
  • frontend/viewer/src/lib/utils.ts
  • frontend/viewer/src/lib/views/entity-config.ts
  • frontend/viewer/src/lib/views/view-data.ts
  • frontend/viewer/src/locales/en.po
  • frontend/viewer/src/locales/es.po
  • frontend/viewer/src/locales/fr.po
  • frontend/viewer/src/locales/id.po
  • frontend/viewer/src/locales/ko.po
  • frontend/viewer/src/locales/ms.po
  • frontend/viewer/src/locales/sw.po
  • frontend/viewer/src/locales/vi.po
  • frontend/viewer/src/project/data/index.ts
  • frontend/viewer/src/project/data/variant-types.ts
  • frontend/viewer/src/project/demo/demo-entry-data.ts
  • frontend/viewer/src/project/demo/in-memory-demo-api.ts
  • frontend/viewer/src/stories/editor/entity-primitives/entry-editor-primitive.stories.svelte
  • frontend/viewer/tests/entry-api-helper.ts
  • frontend/viewer/tests/variants.test.ts

Comment thread backend/FwLite/LcmCrdt/LcmCrdtKernel.cs
Comment thread backend/FwLite/VARIANTS.md
Comment thread frontend/viewer/src/lib/entry-editor/field-editors/VariantOf.svelte
myieye and others added 4 commits July 4, 2026 17:03
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Cycle checks now share one liblcm-faithful walk (ComponentGraph): sense-targeted
  links resolve to the owning entry without recursing (LexEntry.AllComponents), and
  AddEntryComponentChange walks the combined complex-form + variant graph like
  liblcm instead of complex forms only
- Per-link edits split a shared (multi-component) variant ref before mutating so
  sibling links keep their own Types/HideMinorEntry/Comment
- Variant reads skip non-entry/non-sense components instead of wedging the entry
- HideMinorEntry only written when the bool view flips (LCM reserves a bitfield)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itfield

Mutation-tested the new cycle/shared-ref guards (3/3 mutants killed); the
surviving would-be mutant exposed the missing HideMinorEntry bitfield test.
Also docs: fleet-skew rollout note for AddEntryComponentChange, badge and
type-seeding follow-ups, SubmitUpdateVariant asymmetry rationale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hahn-kev hahn-kev self-requested a review July 6, 2026 04:43
Comment thread backend/FwLite/MiniLcm/Models/Variant.cs

@hahn-kev hahn-kev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet done, but there's some stuff to do still

Comment thread backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs Outdated
Comment thread backend/FwLite/MiniLcm/Models/Variant.cs Outdated
Comment thread backend/FwLite/MiniLcm/Validators/MiniLcmValidators.cs
Comment thread backend/FwLite/MiniLcm/SyncHelpers/VariantSync.cs Outdated
Comment thread backend/FwLite/MiniLcm.Tests/FluentAssertGlobalConfig.cs Outdated
Comment thread backend/FwLite/MiniLcm/Validators/VariantTypeValidator.cs Outdated
Comment thread backend/FwLite/MiniLcm/CreateEntryOptions.cs Outdated
Comment thread backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs Outdated
Comment thread backend/FwLite/MiniLcm/ProjectSnapshot.cs
myieye and others added 3 commits July 6, 2026 10:15
- BeaKona forwarders bypassed validation on SubmitCreateVariant and
  SubmitUpdateVariant; both now validate (same class of gap as #2362)
- New VariantUpdateValidator rejects patches to Types (incl. by index,
  via new DoesNotChangePropertyOrChildren), endpoints, derived
  headwords, DeletedAt and Id
- VariantType and ComplexFormType names now reject empty per-WS values
- CreateEntryOptions.IncludeComplexFormsAndComponents renamed to
  IncludeEntryReferences (it gates variants too); generated TS updated
- BoolDiff helper (mirrors IntegerDiff); ToVariants flattened to
  Concat; FluentAssert Id-exclusion no longer names one type''s members;
  ProjectSnapshot.VariantTypes legacy-null note sharpened

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FLEx lets users reorder a ref''s VariantEntryTypesRS (right-click, move
left/right); syncing types as a set silently lost that order. Adds
SetVariantTypesOrder to IMiniLcmWriteApi (both implementations, dry-run,
wrappers, notify) and SetVariantTypesOrderChange (unlisted types keep
their relative order after listed ones, so concurrent type adds merge).
VariantSync resets order after the add/remove diff whenever it cannot
have landed in after-order. Variant link lists themselves stay
unordered (decision 6, amended).

Covered by shared conformance tests (both impls), a CRDT change test
incl. the concurrent-add merge, and a full FwData<->CRDT sync
round-trip; change-model/regression verified files regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Entry list rows show a muted "Variant" badge next to the headword,
  with the main entries in the tooltip
- The dictionary preview renders "var. of X" (classic) / "variant of X"
  (lite) after a variant''s headword, print-dictionary style
- Custom views already inherit the variantOf/variants toggles via
  entityConfig; locked with a contract test
- i18n extracted with translator context; Playwright coverage for badge
  and preview

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@myieye myieye marked this pull request as draft July 6, 2026 09:34
The whole-list SetVariantTypesOrderChange clobbered concurrent
reorders; per Tim''s review, type order now works like sense pictures:
Variant.Types holds VariantTypeRef objects ({typeId, fractional Order},
which also removes the stale-embedded-Name wart from decision 8),
AddVariantType takes a BetweenPosition, MoveVariantType replaces the
list-order API, and ReorderVariantTypeChange merges per type under
concurrency. VariantSync diffs types with DiffOrderable.

Regenerated: change/snapshot regression data (old branch-era shapes
auto-migrated to the legacy files; the never-shipped
SetVariantTypesOrderChange entry removed — its type no longer exists),
DbModel/ChangeModels snapshots, sena-3-live snapshot, TS types
(IVariantTypeRef).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@myieye

myieye commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by a 3-PR stack for chunked review and merge (content-identical: the stack top diffs empty against this branch merged with develop):

  1. Add variant model, CRDT changes, FwData bridge and sync (1/3) #2416 feat/variants-model-sync — model through sync (open for review)
  2. feat/variants-editor — viewer editing UI (stacked, will open after 1 merges)
  3. feat/variants-visibility — variant badges/dictionary preview + custom-view coverage (stacked, will open after 2 merges)

All review feedback here is implemented on the stack (see the inline replies for commit refs), including the per-item variant type ordering rework. Closing.

@myieye myieye closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants