Skip to content

Phase-1 base: Avalonia migration spine (UIMode defaults Legacy)#964

Draft
johnml1135 wants to merge 34 commits into
mainfrom
phase1-base
Draft

Phase-1 base: Avalonia migration spine (UIMode defaults Legacy)#964
johnml1135 wants to merge 34 commits into
mainfrom
phase1-base

Conversation

@johnml1135

@johnml1135 johnml1135 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

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 UIMode setting, which defaults to Legacy (Src/Common/FwUtils/Properties/Settings.Designer.cs) — so default users see no change.

What this PR contains

  • The Avalonia migration framework: region/composer (FullEntryRegionComposer), view-definition IR, owned controls, seam contracts, plugin registry.
  • The base detail-editor surfaces active under UIMode=New: lexiconEdit, lexiconEditPopup, notebookEdit, posEdit.
  • The browse table view code (LexicalBrowseView, LexicalBrowseHostControl, BulkEditBarView, ClerkBrowse*) and its RecordBrowseView wiring — shipped dormant (it's fused to base wiring and can't be cleanly carved out; activated by the table follow-up).
  • Skills/infra, the two-phase plan, and the migration program docs (in openspec/).
  • Back-out of 4 cleanly-removable unwired Avalonia dialogs (SpecialCharacter, WritingSystemProperties, DeleteConfirmation, LexReferenceDetails); 9 woven-in dialogs ride inert behind 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.Phase1FollowUpSurfaceTools and LexicalEditSurfaceResolver.Phase1FollowUpBrowseTools; the migration skill documents the activation recipe.

Stack (each merges into the one above)

  1. thismain
  2. phase1-followup-interlinearphase1-base
  3. phase1-followup-rulephase1-followup-interlinear
  4. phase1-followup-tablephase1-followup-rule

Migration per-screen docs (the basis for JIRA tickets) are on the separate never-merged phase1-docs draft.

Verification

Whole-solution build green; census 10/10, resolver 38/38. Draft until the stack is reviewed top-to-bottom.


This change is Reviewable

johnml1135 and others added 30 commits June 22, 2026 06:41
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`
Remove build flag

Updates

Add testing

Phases 3+4

Refined plan

Update plan.
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>
johnml1135 and others added 4 commits June 24, 2026 15:25
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant