Phase-1 base: Avalonia migration spine (UIMode defaults Legacy)#964
Draft
johnml1135 wants to merge 34 commits into
Draft
Phase-1 base: Avalonia migration spine (UIMode defaults Legacy)#964johnml1135 wants to merge 34 commits into
johnml1135 wants to merge 34 commits into
Conversation
Add FieldWorks Avalonia migration review skills Narrow Phase 1-2 Avalonia migration foundation Tests: de-brittle filter/morph type tests - Avoid localized UI strings in BulkEditBarTests filter baseline - Stop using reflection in MorphTypeAtomicLauncherTests - Fix ViewsInterfaces duplicate TargetFrameworkAttribute build docs: consolidate Avalonia migration onto hybrid roadmap and POC spike Sequence the Avalonia migration as one gated path: POC spike -> DataTree region (Plan A) -> Lexical Edit program (Plan B) -> shell. Adds the avalonia-migration-roadmap umbrella change and the lexical-edit-avalonia-poc-spike change (flagged, in-proc net48 dual-run, density/parity evidence). Brings the datatree-model-view-separation plan onto this branch as the first migrated region with a hybrid-alignment note, and records the approach comparison and recommendation. test: add deterministic semantic-snapshot baseline for POC parity Locks the normalized per-slice snapshot (label, field, flid, editor, visibility, focus order, a11y) that the Avalonia POC slice must reproduce, and asserts it is deterministic across realizations. All expected values reuse those already proven by CfAndBib_SemanticSliceBaselineCapturesStableBindingsAndFocusOrder. feat: prove Avalonia-on-net48 POC spike for Lexical Edit Implements lexical-edit-avalonia-poc-spike as an isolated, flag-gated proof of concept under Src/Common/FwAvalonia (intentionally not in the traversal build or solution yet, so it cannot break the default build). Evidence executed on net48 with Avalonia 11.3.17: - restore + build of the library and headless test project succeed - 20 headless/unit tests pass (dotnet test), covering the two-adapter flag (default WinForms; no Avalonia runtime constructed when off), the three-editor slice, fenced commit/cancel, morph-type popup focus return, writing-system fonts, and a no-native/no-Graphite reference audit Pins Avalonia to 11.3.x in CPM because 12.x dropped netstandard2.0 and cannot load on net48; Avalonia.Win32.Interoperability (net461) restores and builds on net48, confirming the in-process embedding path. Live embedding into RecordEditView and DPI density screenshots require the running app and are deferred to the regional migration (Gate 0 follow-up); see spike-evidence.md. Recommendation: GO. feat: add Lexical Edit migration seams and typed view-definition IR Implements sections 3 (refactor seams) and 4 (typed view definition + XML import) of lexical-edit-avalonia-migration as isolated, tested code in Src/Common/FwAvalonia (not in the traversal build yet, like the POC). Seams (framework-neutral contracts + pure implementations + tests): - ILexicalRefreshCoordinator / RefreshCoordinator: pure model of the DataTree DoNotRefresh/RefreshPending gate (LT-22414) - ILexicalEditorRegistry / LexicalEditorRegistry: editor-key boundary in front of SliceFactory with fallback-to-legacy - IEditSession (PocEditSession now implements it); IUiScheduler, IRegionLifetime, IPropertyStateStore implementations - MorphTypeSwapLogic humble object mirroring MorphTypeAtomicLauncher IsStemType and the stem/affix data-loss decision Typed view definition (sections 4.1-4.6): - ViewDefinitionModel/ViewNode immutable IR with deterministic snapshot - XmlLayoutImporter parses the real Parts/Layout schema (parts, grouping slices, obj/seq, indent, custom-field placeholder, visibility/expansion overrides) and raises diagnostics for dynamic/unknown/obsolete editors and unresolved parts, never throwing - EditorKindMap classifies editors faithfully to SliceFactory's switch - ViewDefinitionCompiler/Cache with content-fingerprint keys, invalidation, and cancellable off-thread compile over immutable snapshots Evidence: dotnet test on net48 passes 67 tests (47 new). Live wiring into DataTree/SliceFactory/RecordEditView is deferred to the regional migration; task notes mark contract-vs-wired status honestly. test: add section-2 characterization coverage before refactor Retroactively completes the "test coverage before refactor" tasks (2.5-2.7) of lexical-edit-avalonia-migration with tests that run against the REAL WinForms DataTree/Slice/RenderVerification code on net48, locking current behavior so the Avalonia refactor is protected. DetailControlsTests (real DataTree/Slice, 11 tests): - DataTreeUndoRedoCharacterizationTests: multistring CitationForm/Bibliography edits revert and replay; multiple edits in one task form a single undo step; consecutive edits are distinct steps; a freshly built slice reflects the reverted model. Uses the base action handler + UndoableUnitOfWorkHelper. - DataTreeDisposalCharacterizationTests: Dispose cascades to slices, removes the LCModel notification (no throw on later change), is idempotent, and is safe with a current slice; slices expose AccessibleName == label and a stable focus order (in-process accessibility substitute for 2.4). RenderVerification (failure-artifact bundling, 4 tests): - RenderFailureArtifactBundler bundles received/diff images + a failure-summary.json into a CI-discoverable folder on a failed render/parity verification; wired into DataTreeRenderTests.VerifyDataTreeBitmap. Compiled into RenderTestInfrastructure alongside RenderSnapshotVerifier so the result type is in scope; covered by RenderFailureArtifactBundlerTests. Evidence: dotnet test on net48 passes all 15 new tests. True UIA2/FlaUI baselines (2.4) and keyboard/IME/localization characterization (2.7 remainder) still need a running app host and remain pending; tasks.md notes this honestly. build: make Avalonia path net48-only and align package pins Keep the Avalonia spike strictly on .NET Framework 4.8 for now. - `build.ps1 -BuildAvalonia` now filters optional Avalonia projects to those that target `net48`, skips non-net48 hosts/modules with an explicit message, and avoids double-building the same project when `-Project` already points at an Avalonia csproj. - `Directory.Packages.props` now pins `HarfBuzzSharp` and its Win32 native assets to 8.3.1.1, matching Avalonia 11.3.17 and removing the NU1109 downgrade failure for the net48 Avalonia spike. Validated: - `dotnet msbuild Src/Common/FwAvalonia/FwAvalonia.csproj` with `/t:Restore;Build` succeeds on net48. - `dotnet test Src/Common/FwAvalonia/FwAvaloniaTests/FwAvaloniaTests.csproj` still passes (67 tests). - `build.ps1 -BuildAvalonia` with `-Project` set to `Src/Common/FwAvalonia/FwAvalonia.csproj` succeeds and reports that the existing preview host is net8-based and outside this branch's net48-only policy. feat: add net48 Avalonia preview host and UIA smoke tests Pull the preview-host idea onto this branch, but refactor it to the branch's net48-only policy instead of the prototype branch's net8 shape. Adds a new net48 `FwAvaloniaPreviewHost` that discovers preview modules via assembly attributes in `FwAvalonia`, along with a runner script at `scripts/Agent/Run-AvaloniaPreview.ps1`. Wires the current lexical-edit POC into that host with: - `FwPreviewModuleAttribute` / `IFwPreviewDataProvider` - `PocPreviewWindow` + `PocPreviewDataProvider` - stable Avalonia automation IDs/names on the slice, text editors, labels, and morph-type chooser Adds native desktop automation tests in `FwAvaloniaPreviewHostTests` using `System.Windows.Automation` that launch the real preview-host exe and verify: - the main preview window and core controls expose stable automation IDs - the morph-type button supports InvokePattern and shows the popup list Updates `build.ps1 -BuildAvalonia` so the optional Avalonia lane also builds `FwAvaloniaPreviewHostTests` when `-BuildTests` is requested. Validated: - `dotnet build` `Src/Common/FwAvaloniaPreviewHost/FwAvaloniaPreviewHost.csproj` - `dotnet test` `Src/Common/FwAvaloniaPreviewHost/FwAvaloniaPreviewHostTests/FwAvaloniaPreviewHostTests.csproj` passes repeatedly (2 UIA tests) - `scripts/Agent/Run-AvaloniaPreview.ps1 -BuildOnly` - the exact previously failing command now succeeds: `./build.ps1 -BuildAvalonia -Project` `"Src/Common/FwAvalonia/FwAvalonia.csproj" -NodeReuse $false` - `./build.ps1 -BuildAvalonia -BuildTests -Project` `"Src/Common/FwAvaloniaPreviewHost/FwAvaloniaPreviewHost.csproj"` `-SkipRestore -SkipDependencyCheck -NodeReuse $false` succeeds feat: add net48 Avalonia preview host and UIA smoke tests Pull the preview-host idea onto this branch, but refactor it to the branch's net48-only policy instead of the prototype branch's net8 shape. Adds a new net48 `FwAvaloniaPreviewHost` that discovers preview modules via assembly attributes in `FwAvalonia`, along with a runner script at `scripts/Agent/Run-AvaloniaPreview.ps1`. Wires the current lexical-edit POC into that host with: - `FwPreviewModuleAttribute` / `IFwPreviewDataProvider` - `PocPreviewWindow` + `PocPreviewDataProvider` - stable Avalonia automation IDs/names on the slice, text editors, labels, and morph-type chooser Adds native desktop automation tests in `FwAvaloniaPreviewHostTests` using `System.Windows.Automation` that launch the real preview-host exe and verify: - the main preview window and core controls expose stable automation IDs - the morph-type button supports InvokePattern and shows the popup list Updates `build.ps1 -BuildAvalonia` so the optional Avalonia lane also builds `FwAvaloniaPreviewHostTests` when `-BuildTests` is requested. Validated: - `dotnet build` `Src/Common/FwAvaloniaPreviewHost/FwAvaloniaPreviewHost.csproj` - the preview-host UIA test project passes repeatedly (2 UIA tests) - `scripts/Agent/Run-AvaloniaPreview.ps1 -BuildOnly` - the exact previously failing command now succeeds: `./build.ps1 -BuildAvalonia -Project` `"Src/Common/FwAvalonia/FwAvalonia.csproj" -NodeReuse $false` - `./build.ps1 -BuildAvalonia -BuildTests -Project` `FwAvaloniaPreviewHost.csproj` `-SkipRestore -SkipDependencyCheck -NodeReuse $false` succeeds feat: wire RecordEditView to the net48 Avalonia POC path Integrate the real app-side feature flag path for the lexical-edit Avalonia POC while keeping the WinForms DataTree path unchanged by default. Changes: - `RecordEditView` now uses `LexicalEditSurfaceResolver` and `LexicalEditSurfaceFactory` to select the visible surface. - When `FW_AVALONIA_LEXEDIT` is enabled, `RecordEditView` swaps the visible control to `PocWinFormsHostControl`, a WinForms wrapper around the Avalonia POC slice hosted through `WinFormsAvaloniaControlHost`. - `LexicalEditPocMapper` projects the current `LexEntry` into the detached DTO used by the Avalonia POC (lexeme form, morph type, first-sense gloss). - `xWorks` now references `FwAvalonia`; Avalonia package references are kept local to `FwAvalonia` so they do not pollute the `xWorks` restore graph. - The preview host and its UIA tests now use isolated `bin` outputs instead of the shared `Output/Debug` folder, avoiding runtime assembly-version clashes. Validated: - `dotnet build Src/xWorks/xWorks.csproj` - `dotnet build Src/xWorks/xWorksTests/xWorksTests.csproj` - `dotnet test Src/xWorks/xWorksTests/xWorksTests.csproj` with the `LexicalEditPocMapperTests` filter - `dotnet test` on the preview-host UIA test project passes - `./build.ps1 -BuildAvalonia -Project "Src/xWorks/xWorks.csproj"` with `-SkipRestore -SkipDependencyCheck -NodeReuse $false` - `./build.ps1 -BuildAvalonia -Project` `"Src/Common/FwAvalonia/FwAvalonia.csproj" -NodeReuse $false` feat: add persisted UIMode preference for lexical edit UI Introduce an app-wide user preference named `UIMode` with values `Legacy` and `New`. The preference is persisted in `FwApplicationSettings` and mirrored into the active `PropertyTable` at startup so existing colleague/property-change broadcasts can react to it immediately. `LexOptionsDlg` now exposes the setting on the Interface tab. When the user changes it and clicks OK: - the new mode is saved to app settings - the runtime `PropertyTable` mirror is updated - the current lexical edit view reloads without requiring an app restart `RecordEditView` now resolves its visible surface from the persisted UIMode (preference first, env var still available as a developer override), lazily initializes the hidden legacy DataTree and the embedded Avalonia host, and switches between them live when the UIMode property changes. Validated: - `dotnet build Src/Common/FwUtils/FwUtils.csproj` - `dotnet build Src/LexText/LexTextControls/LexTextControls.csproj` - `dotnet build Src/xWorks/xWorks.csproj` - `dotnet build Src/Common/FwAvalonia/FwAvaloniaTests/FwAvaloniaTests.csproj` - `dotnet test Src/Common/FwAvalonia/FwAvaloniaTests/FwAvaloniaTests.csproj` with `LexicalEditSurfaceResolverTests` - `dotnet test Src/xWorks/xWorksTests/xWorksTests.csproj` with `LexicalEditPocMapperTests` - `dotnet test` on the preview-host UIA test project - `./build.ps1 -BuildAvalonia -Project "Src/xWorks/xWorks.csproj"` with `-SkipRestore -SkipDependencyCheck -NodeReuse $false`
Pull out Graphite decommissioning to another spec. Lexical Edit view almost there Fix right clicks - fix crashing First AI review Half implemented blockers
Bug fixes and cleanup Fix up multiselect from list Add remaining custom fields ghost lexical reference fields Openspec for multi-writing-system Retire POC LexReferenceMultiSlice Poc cleanup and initial 6.13 work multi-writing-system - next chunk Almost done with mult-writing-systems Further cleanup Almost ready for PR
Getting towards phases 1-4 done
add openspec change for editable table
Intermediate - almost done
Add dialog-MVVM headless test + spike review (Stage 1.2)
Verified end to end: FwAvaloniaDialogs (XAML + CommunityToolkit.Mvvm +
compiled bindings) builds on net48 through build.ps1 (exit 0), and the
headless runtime tests pass 4/4 (compiled bindings both directions,
OkCommand/CancelCommand fire, four tabs load).
- FwAvaloniaDialogsTests: headless [AvaloniaTest] suite + TestAppBuilder
- FwAvaloniaDialogs.csproj: exclude nested test files from the library glob
(mirrors FwAvalonia.csproj's FwAvaloniaTests exclusion)
- build.ps1 / FieldWorks.proj: build the test in the Avalonia loop; exclude
it from the sln-restore traversal (sln entry is the clean follow-up)
- reviews/dialog-mvvm-spike-review.md: approach + scalability assessment
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add FwAvaloniaDialogs to FieldWorks.sln + dialog-conversion skill
- FieldWorks.sln: add FwAvaloniaDialogs + FwAvaloniaDialogsTests so they
restore and open/build in Visual Studio. They still build in build.ps1's
dedicated Avalonia loop and stay excluded from the FieldWorks.proj
traversal, keeping the XAML compile on that isolated, proven path.
Verified: test.ps1 -TestProject FwAvaloniaDialogsTests -> 4/4, exit 0.
- fieldworks-avalonia-ui skill: add "Converting a WinForms dialog (MVVM kit)"
section + dialog-kit canonical pointers, and a full playbook at
references/dialog-conversion.md (3-artifact template, coexistence modality,
build wiring, spike gotchas, author tiers/scope).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Finish dialog foundation: host-modal wrapper + shared Avalonia init
Makes the MVVM dialog kit turn-key — a new dialog is now "view + VM + ShowModal".
- AvaloniaDialogHost.ShowModal(owner, dialogBody, vm, title): shows a dialog
UserControl inside a WinForms-owned modal Form during coexistence
(dialog-ownership.md: owner-relative, restores focus), returns the accepted
result. The view-model implements IDialogViewModel and raises
CloseRequested(bool) from OK/Cancel — no windowing in the VM. The WireClose
seam is unit-tested.
- FwAvaloniaRuntime.EnsureInitialized: single shared Avalonia init guard
(SetupWithoutStarting must run once); AvaloniaRegionHostControl refactored
to funnel through it.
- OptionsDialogViewModel implements IDialogViewModel.
- Tests: VM close contract + WireClose forward/unsubscribe -> FwAvaloniaDialogsTests 7/7;
FwAvalonia host/surface/region unchanged -> 134/134.
- fieldworks-avalonia-ui skill + spike review updated: host-modal wrapper delivered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Localize the Options dialog via per-project .resx (FwAvaloniaDialogsStrings)
Integrate localization into the dialog-MVVM kit, following the established
two-lane convention (product messages -> .resx + hand-written ResourceManager
accessor, keyed off the project RootNamespace for Crowdin satellite builds).
- Add FwAvaloniaDialogsStrings.resx (14 keyed entries with translator comments)
and the FwAvaloniaDialogsStrings.cs accessor (mirrors FwAvaloniaStrings.cs;
ResourceManager "FwAvaloniaDialogs.FwAvaloniaDialogsStrings"). Each Avalonia UI
project owns its own product-message resources / satellite.
- Rebind OptionsDialogView.axaml to {x:Static res:FwAvaloniaDialogsStrings.X}
for all visible text; AutomationIds stay nonlocalized; combo item values
(language codes / channel names) stay data.
- Add two tests: Strings_ResolveFromEmbeddedResx (accessor/resx wiring) and
View_BindsLocalizedStrings_NotHardcodedEnglish (proves the x:Static binding).
9/9 FwAvaloniaDialogsTests pass; build green on net48.
- Document the pattern in the skills: dialog-conversion.md (§1 template, §5
localization) and fieldworks-localization-review SKILL.md lane 2 (per-project
resources: foundation FwAvaloniaStrings, dialogs FwAvaloniaDialogsStrings).
No foundation change needed: per-project .resx is SDK-default-embedded and the
RootNamespace was already set.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Virtualization table
Take work from editable-table branch
Updates from review
Updates from test coverage review
More updates from review
fix bugs
Headless integration tests
Update skills
Table render updates
fix more bugs
Further refinement
Updates from reviews
Fixes
Many dialogs More dialogs and parity More dialog progress, localizations with L10Sharp More localization cleanup - more dialogs and gaps More dialogs and feature parity Updating dialog visuals Add visual snapshots Update dialogs Many dialog updates
Coming into home base of first half of Avalonia migration A lot more work done More progress Implemented? Getting closer Two new openspecs for interliner and rule formula refined plans
Capture-MenuDialogs.ps1 drives the running FLEx app to screenshot legacy dialogs the headless harness cannot construct (Gecko / live IVwRootSite / clerk-backed / bespoke-object dialogs). Techniques: native System.Windows.Automation to invoke menus (modal-Invoke timeout = success signal), defeating the foreground lock with a synthetic Alt-tap so real mouse clicks land, Win32 EnumWindows popup enumeration + whitespace-normalized name matching for multi-level cascades, an in-modal postClicks step (Pane-aware: FLEx exposes buttons as controlType Pane) for button-launched sub-dialogs, and a right-click context-menu path. Read-only: every dialog closed with WM_CLOSE (Cancel); no project modified. Captured 15 previously-uncaptured/headless-impossible dialogs live (fw-styles, insert-record, restore-project, fw-delete-project, dictionary-configuration [Gecko], restore-defaults, configure-interlin, try-a-word, parser-parameters, interlinear-import, sfm-to-texts, interlinear-export, export-dialog, help-about, dictionary-config-manager). capture-ledger.md records the per-dialog technique and the precise remaining boundary. ScreenshotHarnessTests.cs gains the IVwRootSite/SimpleRootSite ctor override. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture-MenuDialogs.ps1 gains per-tab capture (tabLabels/tabClicks: click each WinForms tab header by window-relative coordinate, since the tabs are a Win32 SysTabControl not exposed as UIA TabItems and Ctrl+Tab only advances once before moving focus within the page), plus preClick (select a row before a selection-gated menu) and a right-click context-menu path. Captured all 5 fw-styles tabs (General/Font/Paragraph/Bullets and Numbering/Border) and wired them into styles.md (tab snapshots 18 -> 23). Fixed four wire-script "first-wins" collisions where a backtick class-mention stole another doc's image: styles-modified <-> update-report, dictionary-config-mgr <-> xml-doc-configure, plus the earlier styles/apply-style and restore-project/overwrite fixes. Each doc now references its own capture; no orphans remain. dictionary-config-mgr marked live-capture/on-pickup (NRE'd headless, no standalone menu entry). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OptionsDialogViewModel gains a SelectedTabIndex observable property and an optional initialTab ctor parameter (0=General,1=Plugins,2=Privacy,3=Updates; clamped); the view binds TabControl.SelectedIndex two-way. Callers can open the dialog on a later tab at construction or set SelectedTabIndex any time (deep links / per-tab parity screenshots). Backward compatible: existing callers default to tab 0. Adds InitialTab_* tests (clamp + a render test asserting the dialog opens on the requested tab); full Options suite green (13/13). Note: OptionsDialogView.axaml and OptionsDialogTests.cs also carry concurrent accessibility-mnemonic edits (Ok/Cancel AccessText) from the in-flight cross-cutting review, bundled here only because they co-occupy these files on this branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Delete three files that should never have landed: a scratchpad temp file committed with a mangled AppData path, findings_6-23-2026.md (agent review scratch), and EVIDENCE_CRITERA.md (an unrelated WiX-installer doc). Add .gitignore rules (/findings_*.md, *scratchpad*) so they can't reappear. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…itingSystemProperties) First two of the 13 deferred dialogs to back out for the Phase-1 base PR. Both were test-only (no launcher, no call site — verified), so this is a pure file removal; the FwAvaloniaDialogs product assembly compiles clean without them. Their migration docs remain (Docs/migration) as the basis for follow-up JIRA tickets. Note: the FwAvaloniaDialogsTests project currently fails to build due to an unrelated concurrent change (AccessText references in DialogKeyboardA11yTests.cs / OptionsDialogTests.cs); that break is not from this commit and must be resolved before the test suite can run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Third deferred dialog backed out. Removed both New-UI gate blocks in LexReferenceMultiSlice.cs (the WinForms ConfirmDeleteObjectDlg path is preserved intact below each gate), and deleted LcmDeleteObjectLauncher + DeleteConfirmationDialog view/VM + their tests. Only call site was LexReferenceMultiSlice (verified no other refs). Migration doc retained for the JIRA follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Primitives The a11y-mnemonic tests referenced AccessText with only `using Avalonia.Controls;`, but in Avalonia 11.3 AccessText is Avalonia.Controls.Primitives.AccessText — so the type didn't resolve (CS0246) and the whole test project failed to build. Added the Primitives using to both files. Build green, 300/300 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ved) Fourth and final cleanly-standalone deferred dialog. Removed the New-UI gate in LexReferenceMultiSlice (the WinForms LexReferenceDetailsDlg path is preserved below it) and deleted LcmLexReferenceDetailsLauncher + LexReferenceDetailsDialog view/VM + tests. Reconciliation note: the original "13 to back out" reduces to these 4 standalone utility dialogs (SpecialCharacter, WritingSystemProperties, DeleteConfirmation, LexReferenceDetails). The other 9 are KEPT for principled reasons: CreateFeature (the kept InsertEntry dialog depends on it); ConfigureColumns/FilterFor/DateRangeFilter/FindReplace (table-surface components -> ride inert with the table follow-up per the keep-table-inert decision); AddNewSense/MsaCreator/FeatureChooser (woven into the kept InsertEntry MSA subsystem); PictureProperties (part of the kept detail-editor media services). Each retains its migration doc for the JIRA follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (decision #2) Keep the follow-up surfaces' code in the base PR but dormant, by registration rather than comments (a real gate): split the active tool lists so only the detail-editor tools (lexiconEdit/lexiconEditPopup/notebookEdit/posEdit) advertise the Avalonia edit surface, and empty the Avalonia browse-table tool list entirely. The deferred tools move to public Phase1FollowUpSurfaceTools / Phase1FollowUpBrowseTools arrays that document the exact one-line "flip" each follow-up PR performs to activate its surface. Effect: under UIMode=New, Analyses (interlinear), the 6 rule-formula tools, and every browse tool fall back to the legacy WinForms surface in the base PR. Verified by new InertFollowUpSurfacesFallBackToLegacy_{EditSurface,BrowseTable} tests + BaseDetailEditorTools_StayActive; updated the prior table-active browse tests to the inert expectation. 53/53 resolver tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 7 deferred follow-up tools (Analyses + the 6 Grammar rule-formula editors) are intentionally NOT registered in DefaultSupportedTools for the base PR, so they fall back to legacy WinForms under UIMode=New. Remove those 7 TestCases from RegisteredRecordEditTools_ResolveToAvalonia _WhenUIModeIsNew (keeping notebookEdit + posEdit, the active base tools). A comment points at LexicalEditSurfaceRegistry.Phase1FollowUpSurfaceTools where each follow-up PR re-activates its tool. Note: LexiconEditTool_FlipNewLegacyNew_TearsDownThenRebuildsAvaloniaSurface remains red. That is the pre-existing WIRE-01 (LT-22582) deferred item — the refresh controller lives in the edit-surface composition path for the still-active lexiconEdit tool, unchanged by this inert-gating work. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the three §19g New-UI gate blocks in LexReferenceMultiSlice (DeleteFromReference, DeleteReference, EditReferenceDetails) that routed to the now-deleted LcmDeleteObjectLauncher / LcmLexReferenceDetailsLauncher. Both Avalonia dialogs (DeleteConfirmationDialog, LexReferenceDetailsDialog) and their launchers + tests were removed earlier in this back-out; this drops their last call sites so the legacy WinForms confirmation and LexReferenceDetailsDlg paths are the only ones left. The kept inert dialogs (LinkEntryOrSense link-chooser) are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-up PRs Remove the avalonia-interlinear-editor (9 files) and avalonia-rule-formula-editor (31 files) surface code from the base PR so each lands in its own follow-up PR (decision: "Split base / fat follow-ups"; the browse table stays dormant in base because it is fused to RecordBrowseView wiring). Base-side seams cut so the base compiles + the census passes without them: - RegionEditorPlugins.RegisterBuiltins: drop the 1 interlinear + 5 rule plugin registrations (ChorusNotes/ReversalIndex/MSA/Phonological/AudioVisual stay). - LexemeEditorBurnDownTests.DefaultRegistry_BuiltinsAreExactlyTheLandedWaves: the census now expects exactly the 5 always-on lanes. Each follow-up PR restores its files + registration + census entries and flips its tool name(s) in LexicalEditSurfaceRegistry.Phase1FollowUpSurfaceTools. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Decision #2: the avalonia-migration hub skill now documents the inert follow-up surface mechanism and the exact activation recipe — the two gates (plugin registration vs the surface/tool registry flip), where the inert lists live (Phase1FollowUpSurfaceTools / Phase1FollowUpBrowseTools), the step-by-step turn-on procedure, and that the pinned pre-split commit is the ground truth for the canonical active arrays. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 402-file Docs/migration catalog (per-screen WinForms->Avalonia docs + their captured screenshots) is the JIRA-ticket basis, not mergeable product. It lives solely on the phase1-docs branch (a never-merged draft PR). Removing it from the base PR keeps the four code PRs free of migration documentation; the throwaway ScreenshotHarness tooling stays (it generates those images into Docs/migration). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase-1 base: Avalonia migration spine
First of a 4-PR stack landing Phase 1 of the WinForms→Avalonia migration. Every Avalonia surface is gated behind the
UIModesetting, which defaults toLegacy(Src/Common/FwUtils/Properties/Settings.Designer.cs) — so default users see no change.What this PR contains
FullEntryRegionComposer), view-definition IR, owned controls, seam contracts, plugin registry.UIMode=New:lexiconEdit,lexiconEditPopup,notebookEdit,posEdit.LexicalBrowseView,LexicalBrowseHostControl,BulkEditBarView,ClerkBrowse*) and itsRecordBrowseViewwiring — shipped dormant (it's fused to base wiring and can't be cleanly carved out; activated by the table follow-up).openspec/).UIMode=New.Inert follow-up surfaces
The interlinear and rule-formula detail editors are carved out to the stacked follow-up PRs below (their view files are not in this PR). The browse table ships here but inert. The inert lists are
LexicalEditSurfaceRegistry.Phase1FollowUpSurfaceToolsandLexicalEditSurfaceResolver.Phase1FollowUpBrowseTools; the migration skill documents the activation recipe.Stack (each merges into the one above)
mainphase1-followup-interlinear→phase1-basephase1-followup-rule→phase1-followup-interlinearphase1-followup-table→phase1-followup-ruleMigration per-screen docs (the basis for JIRA tickets) are on the separate never-merged
phase1-docsdraft.Verification
Whole-solution build green; census 10/10, resolver 38/38. Draft until the stack is reviewed top-to-bottom.
This change is