Skip to content

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

Draft
johnml1135 wants to merge 1 commit into
mainfrom
phase1-base
Draft

Phase-1 base: Avalonia migration spine (UIMode defaults Legacy)#964
johnml1135 wants to merge 1 commit 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 and the roadmap's core proposal/design/tasks/spec, plus the landed openspec change specs (lexical-edit-avalonia-migration, shared-editable-virtualized-table, avalonia-multi-writing-system-text-foundation) — pared back from the original diff (see "Branch cleanup" below).
  • Back-out of 4 cleanly-removable unwired Avalonia dialogs (SpecialCharacter, WritingSystemProperties, DeleteConfirmation, LexReferenceDetails); 13 dialog UIs + a shared MessageBox ride behind UIMode=New, each verified wired to a real WinForms call site.

Inert follow-up surfaces

The interlinear and rule-formula detail editors are carved out to the stacked follow-up PRs below (their openspec proposals and view files are not in this PR). The browse table and ChorusNotesBarControl (the Chorus/FLExBridge notes bar) ship 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) and the full 13-stage migration-program planning material (speculative future-phase work, not needed to review this PR) both live on the separate, never-merged phase1-docs branch (draft PR, explicitly marked do-not-merge).

Verification

Whole-solution build green. Surface-registry census: 6 custom-slice classes classified (LexemeEditorBurnDownTests); 7 tools in LexicalEditSurfaceRegistry.Phase1FollowUpSurfaceTools; 8 tools in LexicalEditSurfaceResolver.Phase1FollowUpBrowseTools. Full CI-equivalent test run passes except 38 pre-existing, environment-specific test failures unrelated to this branch (a cross-worktree test-data collision, fixed separately in #979). Note: two of the hardening test files (RegionCommandAdapterHardeningTests.cs, RegionObjectCommandExecutionTests.cs) run roughly half their cases only on the manual [Explicit] desktop lane, not CI — "tests added" for these files should not be read as "tests running in CI." Draft until the stack is reviewed top-to-bottom.

Branch cleanup (post-review)

A multi-part internal review of this branch (PR_964_review.md, not included in this diff) found and fixed a substantial amount of unrelated or stale content bundled into the original diff. Squashed into this single commit; highlights:

  • Removed content unrelated to the Avalonia migration: an unrelated installer-docs deletion and an ungated Legacy-mode rendering change were reverted, and a misplaced/stale stray doc file was dropped.
  • Split two unrelated-but-legitimate fixes into their own PRs: #978 (VersionInfoProvider copyright/version-string bugs, a stale RegFree.targets entry, an opsx-prompt refactor) and #979 (a pre-existing cross-worktree test-collision bug in RealDataTestsBase, found while verifying this branch but unrelated to it).
  • Fixed a real build break (RecordBrowseView.cs used a pub/sub API signature main had already replaced) and a real product bug (the Avalonia refresh controller could stay unwired when a tool loads directly into UIMode=New) — and the test proving it (RecordEditViewSwitchTests) is now green: the shared idle-queue test-drain helper had never actually worked in this environment (it reflected into a private method whose message-pump politeness check always aborted), which also meant 5 test fixtures weren't proving what they looked like they proved. Centralized a correct drain in XWorksAppTestBase, which surfaced and fixed a second bug (2 fixtures missing a layout/parts Inventory bootstrap 2 sibling fixtures already had). All affected tests pass; full xWorksTests suite: 1645 passed, 0 failed.
  • Pared back ~7,500 lines of speculative future-phase openspec planning docs, deleted two fully superseded proposals and stale datatree-model-view-separation specs asserting an architecture that was never built, and removed remaining POC/spike language and stale cross-references repo-wide (including a real stale-default-value bug in Run-AvaloniaPreview.ps1).
  • Gated ChorusNotesBarControl as a Phase-1 follow-up surface (it was live, contradicting its "dormant" framing); wired the one missing UIMode gate (GoLinkEntryDlgListener.OnGotoLexEntry); documented one honest parity deferral (MsaInflectionFeatureListDlgLauncher switch-tools navigation); removed dead API and ~20 orphaned localization keys; strengthened the FwAvalonia engine-isolation audit to match its own documented symbol list; fixed three evidence-language issues in Path3BundleTests; reconciled dialog spacing tokens against real measured WinForms control geometry.
  • Code coverage review: ran line-level coverage analysis across the PR's own added code, found and closed the highest-value real gaps (35 new tests total: MSA-launcher resolver switch/not-found branches, ApplyInflectionFeatures's undo-task-safety null guards, an XmlViewsUtils part-ref regression test, and the pure/testable logic across all remaining under-tested Lcm*Launcher classes), and documented the genuinely modal-locked gates that can't be unit-tested without a production testability seam. Full breakdown below.

9-group breakdown: scope, gaps found, what was fixed vs. left as a finding

Every file in this PR's diff was accounted for in exactly one of the 9 groups below (verified programmatically — zero unclassified) at the time of the review. Full detail, file-by-file evidence, and exact test names are in PR_964_review.md §18. Note: the branch has since been squashed to one commit and rebased onto a newer main; git diff --stat main...phase1-base now reports 560 files (the table below totals 562 from the original review — a ~2-file drift not worth re-deriving the full per-group split for, since no group's conclusion changes).

# Group Files Scope Gaps found Fixed Left as a finding (owner decision needed)
1 Avalonia core frameworkSrc/Common/FwAvalonia/{Region,ViewDefinition,Seams,Preview}/, root FwAvalonia/*, FwAvaloniaPreviewHost/ 84 The framework substrate: XML-to-IR compiler, composer/render layer, framework-neutral seams, preview host 3 1 Preview/ code ships inside the production DLL (excluding it would break FwAvaloniaPreviewHost.exe's current project-reference wiring, a build-topology change); FwAvaloniaStrings.resx has orphaned keys (deleting/rewiring changes shipped localization surface)
2 Avalonia framework + dialog testsFwAvaloniaTests/, FwAvaloniaDialogsTests/, RenderTestInfrastructure/, RenderVerification/ 100 4-tier test suite: unit, headless-UI, visual/snapshot, parity-bundle 2 0 Extracting a shared AvaloniaHeadlessDialogFixtureBase (~24 files) and a shared ViewDefinitionModel test-builder (~9 files) are DRY/maintainability refactors of existing, passing tests, not coverage gaps; real but non-trivial regression risk, recommended as a dedicated follow-up rather than bundled in here
3 Avalonia dialogs (product)FwAvaloniaDialogs/ (excl. tests) 71 MVVM dialog kit: 13 dialog UIs + shared MessageBox 0 -- --
4 Product wiring / integrationSrc/xWorks/*.cs (excl. tests), Common/Controls/, Common/FwUtils/, Common/FieldWorks/, XCore/, Common/Framework/, Common/SimpleRootSite/, Common/ViewsInterfaces/ 62 The highest-risk layer: where a Legacy regression would surface for existing users 3 3 --
5 Src/xWorks/xWorksTests 47 Test evidence for the composer/plugin-registry, the 4 active surfaces, the dormant browse table 2 2 --
6 Src/LexTextLexTextControls/, Lexicon/, Morphology/, Interlinear/, LexTextDll/ 58 ~45 if (UIMode==New) {Avalonia} else {legacy} dialog-launcher gates; 13 new Lcm*Launcher glue classes 1 (coverage) 1 (35 new tests) 3 modal-locked gate/dispatch sites (EntryDlgListener.cs, 3 gates; MSAPopupTreeManager.cs, 2 gates; LexReferenceMultiSlice.GetRootObject) — every path ends in a real modal dialog this codebase deliberately excludes from unit tests; fixing needs a production testability seam, a decision for whoever owns this PR
7 openspec — landed changes + roadmap core 95 The honest record of what shipped (11,321 of 11,993 lines); only 672 lines remain forward-looking, both substantially implemented 1 0 datatree-model-view-separation's one openspec validate --strict failure predates this PR entirely — not this PR's scope to fix
8 .claude/skills + .github 31 Migration hub skill, satellite review skills, dialog-authoring skill, MCP docs 0 -- --
9 Repo mechanics / misc.sln/.proj/Directory.Packages.props/root docs 14 Mechanical project registration + package additions 0 -- --

Totals: 12 gaps found across the PR: 7 fixed (35 new tests + 4 doc/comment corrections), 5 left as explicit findings (2 production-restructuring, 2 test-refactor-only, 1 pre-existing-elsewhere) — none silently dropped.


This change is Reviewable

@github-actions

This comment has been minimized.

johnml1135 added a commit that referenced this pull request Jul 1, 2026
…ing docs

Per deep review of the Phase-1 base PR, this removes ~10,300 lines of
openspec content that does not belong in the base PR:

Deleted entirely (self-declared superseded, or already implemented on a
sibling branch with no home needed here):
- openspec/changes/graphite-transition-support/ (self-labeled superseded
  throughout; content restated elsewhere)
- openspec/changes/fieldworks-avalonia-shell-migration/ (self-labeled
  folded into/superseded by avalonia-end-game)
- openspec/changes/avalonia-interlinear-editor/ (implemented on
  phase1-followup-interlinear, commit 3c5893e)
- openspec/changes/avalonia-rule-formula-editor/ (implemented on
  phase1-followup-rule, commit 2c142bc)

Deleted here for relocation to phase1-docs (speculative future-phase
planning with real future value, not needed to review/merge this PR):
- openspec/changes/avalonia-migration-roadmap/complete-migration-program.md,
  epics/**, reviews/** (JIRA-epic drafting for unstarted stages 5-13)
- openspec/changes/legacy-screenshot-capture/ (dev tooling supporting a
  Docs/migration/ effort this PR isn't carrying)
- openspec/changes/avalonia-end-game/ (depends on a Phase-1 burn-down this
  PR hasn't finished)

Trimmed/deleted within datatree-model-view-separation (this change's own
proposal.md/hybrid-alignment.md already carry a 2026-06-09 supersession
note saying DataTreeModel/SliceSpec/IDataTreeView "should not be built";
these were the pieces that never caught up to that note):
- Deleted specs/datatree-model/spec.md (asserted the abandoned
  DataTreeModel/SliceSpec/IDataTreeView requirements as live ADDED
  reqs); kept specs/datatree-partial-split/spec.md (the partial-class-split
  slice the proposal says remains valid as optional legacy maintenance)
- Deleted three overlapping draft test plans for the abandoned design:
  testing-approach-2.md, test-plan-forms.md, test-plan-forms-future.md
- Deleted stale coverage-gap planning docs:
  specs/changes-from-test-before-refactor/coverage-wave2-test-matrix.md
  and ".../tests to fix coverage gaps.md"
- Trimmed datatree-mental-model.md to the current-state description only,
  removing the "target shape after split" section describing the
  abandoned architecture

Fixed two stale artifacts that never caught up to their sibling
supersession notes:
- avalonia-migration-roadmap/specs/avalonia-migration-roadmap/spec.md:
  added a supersession note to the "DataTree split is the first migrated
  region" requirement and added an as-built scenario describing the
  actual region-model path (ViewDefinitionModel/LexicalEditRegionModel),
  matching the note already in this change's own design.md
- lexical-edit-avalonia-migration/architecture-diagrams.md: removed the
  IPropertyStateStore port node (never built per task 18.6; state flows
  through IRecordNavigationContext + host PropertyTable), annotating the
  Navigation port instead

Kept as-is per review: avalonia-migration-roadmap/{proposal,design,
tasks}.md + specs/ (the ordered roadmap every later stack PR needs),
avalonia-multi-writing-system-text-foundation/ (substantially shipped,
not speculative), and the rest of datatree-model-view-separation
(design.md/tasks.md/proposal.md already carry accurate snapshot framing).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@johnml1135 johnml1135 force-pushed the phase1-base branch 2 times, most recently from 10d7181 to af20c5b Compare July 1, 2026 16:23
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

NUnit Tests

    1 files  ±    0      1 suites  ±0   15m 52s ⏱️ + 5m 10s
6 137 tests +1 838  6 056 ✅ +1 830  81 💤 +8  0 ❌ ±0 
6 146 runs  +1 838  6 065 ✅ +1 830  81 💤 +8  0 ❌ ±0 

Results for commit 718b5fd. ± Comparison against base commit 906e569.

♻️ This comment has been updated with latest results.

@github-actions

This comment has been minimized.

johnml1135 added a commit that referenced this pull request Jul 3, 2026
…ss, openspec

Records accumulated phase-1 working-tree changes not part of the Options-dialog
work: adoption of the shared AvaloniaDialogTestHarness across the dialog test
suites, LexicalBrowse* / ViewDefinition test updates, the FwAvalonia Preview/**
compile exclusion (PR #964 review §4 finding F), preview-host project ref, and
openspec roadmap edits (incl. removing the superseded datatree-model-view-
separation change). Bundled as one checkpoint; the tree builds and all touched
test suites pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

This comment has been minimized.

johnml1135 added a commit that referenced this pull request Jul 3, 2026
Records accumulated phase-1 working-tree changes not part of the Options-dialog
work: adoption of the shared AvaloniaDialogTestHarness across the dialog test
suites, LexicalBrowse* / ViewDefinition test updates, the FwAvalonia Preview/**
compile exclusion (PR #964 review §4 finding F), preview-host project ref, and
openspec roadmap edits (incl. removing the superseded datatree-model-view-
separation change). Bundled as one checkpoint; the tree builds and all touched
test suites pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@johnml1135 johnml1135 force-pushed the phase1-base branch 2 times, most recently from 6636e17 to 40ae9d1 Compare July 3, 2026 20:54
johnml1135 added a commit that referenced this pull request Jul 4, 2026
Stacked on the interlinear follow-up. Restore the rule-formula surface
and activate it:
- add back the 29 rule-formula files (the 5 plugins,
  RuleFormulaModel/RegionEditor + RuleCellCommands, PhEnvironment +
  BasicIPASymbol editors, projector/sinks/options + deriver, and all
  their tests incl. SupportingEditorComposeTests)
- restore the 5 plugin registrations in RegionEditorPlugins
- restore the 5 rule class names in the burn-down census
- FLIP: register the 6 rule tools (PhonologicalRuleEdit,
  EnvironmentEdit, compoundRuleAdvancedEdit, naturalClassedit,
  phonemeEdit, AdhocCoprohibEdit) in LexicalEditFeatureCatalog under a
  new "Grammar rule editors" group (restoring the canonical pre-split
  active set + parity notes); Phase1FollowUpSurfaceTools is now empty
  (both edit follow-ups landed; browse table gated separately)
- add the 6 rule TestCase rows to RegisteredRecordEditTools_ResolveToAvalonia

Rebased onto the squashed phase1-base (post PR #964 review): tool
registration is now catalog-driven, so this flip also adds a new
"Grammar rule editors" group (6 rows) to the Tools->Options "Manage
Individual Features" dialog under UIMode=New.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Jul 4, 2026
Restore the interlinear surface on top of phase1-base and activate it:
- add back the 11 interlinear files (InterlinearRegionEditor + analysis
  model + projector/write-back + plugin + their tests, incl. the
  FwAvalonia model and Visual tests)
- restore the InterlinearSlicePlugin registration in RegionEditorPlugins
- restore the interlinear class name + resolve assertion in the
  burn-down census
- FLIP: register "Analyses" in LexicalEditFeatureCatalog (with new
  display-name/description strings), so it flows into the catalog-
  sourced DefaultSupportedTools and the Words Analyses detail editor
  resolves to Avalonia under UIMode=New; removed from
  Phase1FollowUpSurfaceTools
- add the "Analyses" TestCase back to
  RegisteredRecordEditTools_ResolveToAvalonia

The browse "Analyses" list pane stays inert (table follow-up territory).

Rebased onto the squashed phase1-base (post PR #964 review): the base PR
had since refactored tool registration to be catalog-driven, so this
flip now also adds a "Words Analyses" row to the Tools->Options "Manage
Individual Features" dialog under UIMode=New.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Jul 4, 2026
Stacked on the interlinear follow-up. Restore the rule-formula surface
and activate it:
- add back the 29 rule-formula files (the 5 plugins,
  RuleFormulaModel/RegionEditor + RuleCellCommands, PhEnvironment +
  BasicIPASymbol editors, projector/sinks/options + deriver, and all
  their tests incl. SupportingEditorComposeTests)
- restore the 5 plugin registrations in RegionEditorPlugins
- restore the 5 rule class names in the burn-down census
- FLIP: register the 6 rule tools (PhonologicalRuleEdit,
  EnvironmentEdit, compoundRuleAdvancedEdit, naturalClassedit,
  phonemeEdit, AdhocCoprohibEdit) in LexicalEditFeatureCatalog under a
  new "Grammar rule editors" group (restoring the canonical pre-split
  active set + parity notes); Phase1FollowUpSurfaceTools is now empty
  (both edit follow-ups landed; browse table gated separately)
- add the 6 rule TestCase rows to RegisteredRecordEditTools_ResolveToAvalonia

Rebased onto the squashed phase1-base (post PR #964 review): tool
registration is now catalog-driven, so this flip also adds a new
"Grammar rule editors" group (6 rows) to the Tools->Options "Manage
Individual Features" dialog under UIMode=New.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Jul 4, 2026
Restore the interlinear surface on top of phase1-base and activate it:
- add back the 11 interlinear files (InterlinearRegionEditor + analysis
  model + projector/write-back + plugin + their tests, incl. the
  FwAvalonia model and Visual tests)
- restore the InterlinearSlicePlugin registration in RegionEditorPlugins
- restore the interlinear class name + resolve assertion in the
  burn-down census
- FLIP: register "Analyses" in LexicalEditFeatureCatalog (with new
  display-name/description strings), so it flows into the catalog-
  sourced DefaultSupportedTools and the Words Analyses detail editor
  resolves to Avalonia under UIMode=New; removed from
  Phase1FollowUpSurfaceTools
- add the "Analyses" TestCase back to
  RegisteredRecordEditTools_ResolveToAvalonia

The browse "Analyses" list pane stays inert (table follow-up territory).

Rebased onto the squashed phase1-base (post PR #964 review): the base PR
had since refactored tool registration to be catalog-driven, so this
flip now also adds a "Words Analyses" row to the Tools->Options "Manage
Individual Features" dialog under UIMode=New.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
johnml1135 added a commit that referenced this pull request Jul 4, 2026
Stacked on the interlinear follow-up. Restore the rule-formula surface
and activate it:
- add back the 29 rule-formula files (the 5 plugins,
  RuleFormulaModel/RegionEditor + RuleCellCommands, PhEnvironment +
  BasicIPASymbol editors, projector/sinks/options + deriver, and all
  their tests incl. SupportingEditorComposeTests)
- restore the 5 plugin registrations in RegionEditorPlugins
- restore the 5 rule class names in the burn-down census
- FLIP: register the 6 rule tools (PhonologicalRuleEdit,
  EnvironmentEdit, compoundRuleAdvancedEdit, naturalClassedit,
  phonemeEdit, AdhocCoprohibEdit) in LexicalEditFeatureCatalog under a
  new "Grammar rule editors" group (restoring the canonical pre-split
  active set + parity notes); Phase1FollowUpSurfaceTools is now empty
  (both edit follow-ups landed; browse table gated separately)
- add the 6 rule TestCase rows to RegisteredRecordEditTools_ResolveToAvalonia

Rebased onto the squashed phase1-base (post PR #964 review): tool
registration is now catalog-driven, so this flip also adds a new
"Grammar rule editors" group (6 rows) to the Tools->Options "Manage
Individual Features" dialog under UIMode=New.

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