FieldWorks Context
August 6, 2026 · View on GitHub
This file captures the thin layer of shared language that helps humans and agents talk about this repository without re-explaining the same concepts every session. It is intentionally not a full architecture manual. It should stay biased toward terminology, relationships, invariants, and naming choices that affect planning, navigation, implementation, and reviews.
Scope
- This is the root context for the whole repository.
- It covers repo-wide language shared across product, code, build, test, and installer work.
- If a subtree develops materially different language, add a more local
CONTEXT.mdthere instead of bloating this file.
Canonical Product Terms
- FieldWorks: The preferred default name for the product suite, the repository, and root-level planning language.
- FLEx: Legacy shorthand for FieldWorks Language Explorer. Use it when matching existing code, folders, UI text, integrations, or historical documentation, not as the default root-level product term.
- Language Explorer: The spelled-out legacy product name behind FLEx that still appears in repo paths, UI assets, and integrations.
- FieldWorks.exe: The current host executable for the main application shell.
Disambiguation Rules
- Treat
projectas requiring a qualifier almost always. The word is overloaded in this repo. - Language project: A user/data project inside FieldWorks or FLEx.
- Git repository or repo: The source tree you are editing now.
- MSBuild project: A
.csproj,.vcxproj,.wixproj, or similar build unit. - Installer project: WiX authoring and packaging work under
FLExInstaller/. - Worktree: A git worktree for isolated builds and edits.
Writing system: overloaded — qualify when the distinction matters.- Writing system definition:
WritingSystemDefinition(libpalaso /SIL.WritingSystems); the base writing system class, identified by a BCP-47 language tag. - Core writing system definition:
CoreWritingSystemDefinition(liblcm /SIL.LCModel.Core.WritingSystems); extendsWritingSystemDefinitionwith aHandleand LCM-specific features such as character sets. - Writing system handle: Integer
HandleonCoreWritingSystemDefinition, assigned byWritingSystemManagerwithin a language project. Used for fast text-run lookups; not meaningful outside LCModel. - Writing system tag: BCP-47 string (
LanguageTag/Id) identifying a writing system in persistence and cross-library code. - Vernacular / analysis writing system: The role a writing system plays inside a language project (see Core Domain section).
- Writing system definition:
Core Domain and Product Language
- Language project: A user-managed linguistic dataset opened and edited in FieldWorks.
- Writing system: A configured language/script/orthography used to store and display text.
- Vernacular writing system: A writing system used for source-language data.
- Analysis writing system: A writing system used for glosses, definitions, translated labels, and analysis-oriented text.
ITsString/ TsString: The LCModel-managed text model used for lexicon and Views text, including run-level writing-system and style properties. Cross-framework clipboard and drag/drop interchange serializes it throughTsStringWrapperXML.- Multi-writing-system text: A text value or field that exposes one or more writing-system alternatives and may also preserve run-level writing-system and style metadata inside a single
ITsString. - IME composition: The transient input-method editing state before text is committed. Treat composition behavior and committed text behavior as separate test and parity concerns.
- Lexicon: The lexical data and editing experience in FLEx.
- Interlinear text: Text annotated with multiple aligned linguistic analysis lines.
- Morphology: The part of the system and data model concerned with morphemes, rules, and word analysis.
- Parser: Morphological analysis tooling such as HermitCrab or XAmple.
- Paratext integration: Scripture and lexicon interoperability with Paratext. Implemented across
FwParatextLexiconPlugin,ParatextImport(scripture text import viaParatextImportManager/ParatextSfmImporter), andParatext8Plugin(bridge to Paratext APIs). - Send/Receive: The user-facing synchronization workflow for sharing project data.
- FLEx Bridge: The tool/integration layer used by Send/Receive and related LIFT-based exchange workflows.
Architecture and Codebase Language
- LCModel: The underlying managed data model, caches, services, and related packages used for FieldWorks data access.
- xWorks: The shared application framework and shell infrastructure that hosts major work areas.
- LexText: The FLEx application layer and related lexicon/text-analysis functionality.
- Common: Shared infrastructure, controls, dialogs, utilities, and framework code used across the suite.
- FwKernel and Views: Native rendering and view infrastructure.
- ViewsInterfaces: The managed interface layer generated from native IDL and used across the managed/native boundary.
- Traversal build: The ordered build driven by
FieldWorks.projand invoked viabuild.ps1. - LcmCache: Root entry point to LCModel (
SIL.LCModel); called "the cache" in code and comments. Not a simple data cache — the name is historical. Exposes the language project, writing system factory, action handler, andServiceLocator. - Service locator:
LcmCache.ServiceLocator(ILcmServiceLocator). IoC container for LCModel — the primary way to retrieve repositories, factories, and services. - Unit of work: Groups data-model changes under
IActionHandler. All LCModel writes must occur inside one.UndoableUnitOfWorkHelper(undoable) andNonUndoableUnitOfWorkHelper(non-undoable) are inSIL.LCModel.Infrastructure; use as ausingblock or via their static.Do(...)helpers. - Publish/subscribe system: Messaging system (
IPublisher/ISubscriber,SIL.FieldWorks.Common.FwUtils) viaFwUtils.PublisherandFwUtils.Subscribersingletons. Supports exact-name and prefix subscriptions;PublishAtEndOfActiondefers delivery to end of user action. Event-based problems deserve event-based solutions — avoid state variables for event timing when a deterministic subscribe/unsubscribe solution can be used. - Area: One of the five top-level navigation divisions — Lexicon, Grammar, Words & Texts, Notebook, Lists. Declared in
areaConfiguration.xmland identified by constants inAreaConstants. Each Area has its own sidebar and owns a set of Tools. - Tool: A view or function within an Area, declared in
toolConfiguration.xml. The active Tool per Area is tracked viaToolForAreaNamed_<area>; switching Areas restores the last-used Tool. Navigation is property-driven through the XCore mediator system. - Dictionary configuration: A
.fwdictconfigXML file (DictionaryConfigurationModel) defining which LCModel fields appear in a dictionary view, their order, style, and options. Scoped to one or more Publications. - Publication: A named output target (e.g. a print edition or web view) that dictionary configurations are scoped to.
AllPublicationsapplies a configuration to all current and future publications. - FlexText: An XML interchange format (
.flextext) for interlinear texts, representing analyzed words with morpheme, gloss, and translation annotations. Used for import and export of interlinear data; handled inLexText/Interlinear. - Webonary: An online dictionary publishing service that FieldWorks integrates with as an export target. Implemented in xWorks (
UploadToWebonaryController,WebonaryClient). - Utility: A user-invoked data maintenance or migration tool (e.g. resetting homographs, removing parser annotations, fixing duplicate analyses). Utilities implement
IUtility(FwCoreDlgs), are registered inUtilityCatalogInclude.xmlvia reflection, and run throughUtilityDlg(Tools > Utilities menu). - DistFiles: Runtime assets copied into outputs or installers.
- Detail: In the Avalonia migration, the framework-neutral model of an editing view: a flattened, ordered list of typed fields (
DetailModel/DetailField) composed from the view definition and rendered by the AvaloniaDataTree. A detail model is data; the rendered view is its visible form. It supersedes Region, the migration-invented word this vocabulary replaced — do not reintroduceRegion*names for these concepts. - View definition: The typed IR (
ViewDefinitionModel, aViewNodetree) compiled from the legacy XML Parts/Layout files byViewDefinitionCompilerand cached by(className, layoutName, layoutType, fingerprint). It is the input the composer projects into aDetailModel. - Surface: RETIRED as project vocabulary — it accumulated conflicting scopes (record UIs only, record UIs plus dialogs, any migratable UI). Say the concrete thing: a view (the rendered UI a tool shows for a record — the legacy WinForms
DataTree/BrowseVieweror the AvaloniaDetailHostControl), a dialog, or the UI framework (UIFramework, selected per tool from theUIModesetting viaUIFrameworkResolver/UIFrameworkRegistry). "Surface" survives only in styling vocabulary (the drawn background:FwSurfaceStyles, the surface font) and in the linguistic term "surface form". - Cross-namespace twin: A deliberate reuse of a legacy type name for its Avalonia counterpart (
FwAvalonia.Detail.DataTreebesideDetailControls.DataTree;SliceFactory,MSAGroupBox). Disambiguate with ausingalias at the call site; never rename the type to dodge the collision. The twins cover only the half of the legacy responsibility that still fits — the AvaloniaDataTreerenders a prebuiltDetailModeland does not compose it. - Slice plugin: A custom Avalonia row editor (
ISlicePlugin) registered inSlicePluginRegistryunder the exact legacy layoutclass=string, so migrating a slice edits no layout XML. Registration throws on a double claim: one owner per legacy class. - Unsupported row: The labeled row
SliceFactorybuilds when no field kind, plugin, or control matches. Unmigrated work is always visible and never silently omitted; the set of these rows is the remaining conversion worklist. - Seam: A framework-neutral substitution point that lets the Avalonia layer consume product behavior without referencing LCModel or WinForms —
IEditSession,IUiScheduler,IDetailLifetime,IDetailRefreshCoordinator,IXCoreCommandBridge,IRecordNavigationContextinFwAvalonia/Seams, alongside boundary data contracts such asIFwClipboard. Product implementations live at the xWorks edge. Deliberately narrow: direct Avalonia APIs remain allowed at the UI edge, andSeams/holds only real substitution points — not helpers that merely live near one. - Fenced edit session: One
IEditSessionwrapping one LCModel undo task, opened lazily on the first staged edit and ended exactly once by Commit or Cancel. Prevents orphaned undo tasks; implemented byLcmDetailEditSession. - Settle: The single auto-save policy for an open edit session — commit if valid, otherwise roll back and notify. Invoked on navigation, window deactivate, undo, and teardown (
DetailEditContextHolder.Settle). - Parity: Behavioral/visual equivalence between a legacy WinForms view or dialog and its Avalonia replacement. Gaps are recorded as
// TODOwith the blocking facts named, or as approved divergences -- never left implicit. (The older// PARITYmarker is retired.) - Preview vs POC: In the Avalonia migration, preview means a lightweight sample or design-time path that reuses the shared detail renderer — including the standalone preview host, which runs a view or dialog without a language project; POC refers only to the retired spike/evidence vocabulary and should not name live runtime code paths.
- StringTable localization: The singleton
StringTable(FwUtils) loadsstrings-<locale>.xmlfrom the Language Explorer configuration folder and localizes text that originates in XML configuration files — layout/part labels, browse column headings, and XCore menu/command labels.StringTable.Table.LocalizeAttributeValue(...)(andXmlUtils.GetLocalizedAttributeValue(...)) look the attribute value up in the file'sLocalizedAttributesgroup and return the English value unchanged when no localization exists. .resxlocalization strategy: FieldWorks-owned forms and controls keep their strings in project.resxresources, resolved throughResourceManagerand shipped as satellite assemblies. New FieldWorks-owned UI — including the Avalonia views and dialogs (FwAvaloniaStrings.resx,FwAvaloniaDialogsStrings.resx) — belongs in this strategy.- L10NSharp localization strategy: Dialogs and widgets that come from Palaso, FlexBridge, or Chorus — or FieldWorks UI hosting an L10NSharp localization widget — are localized through the XLIFF-backed
LocalizationManagers created byFieldWorks.InitializeLocalizationManager. It supports runtime UI-language switching, but any host or test process that touches it must initialize at least oneLocalizationManagerfirst. Do not add new L10NSharp usage for FieldWorks-owned strings.
Repo-Wide Invariants
- Native C++ builds before managed code generation and managed projects.
build.ps1is the canonical build entry point.test.ps1is the canonical test entry point.- Registration-free COM is a core deployment/runtime assumption; do not introduce global COM registration behavior.
- User-visible UI strings belong in
.resx, not hardcoded source. - Installer work lives under
FLExInstaller/. - Integration tests often depend on deterministic sample data such as
TestLangProj/. - Worktree-aware scripts are preferred because concurrent work across git worktrees is supported.
- FLEx/Language Explorer is built with architectural boundaries, new dependencies between existing projects must be justified.
Key Relationships
- FieldWorks the repository contains the FLEx application, supporting tools, shared libraries, installer authoring, and docs.
- Native build artifacts feed managed code generation through ViewsInterfaces.
- Send/Receive is a workflow; FLEx Bridge is the underlying integration/tooling layer behind that workflow.
- Writing systems are first-class project configuration, with vernacular and analysis writing systems playing different roles.
Good Naming Pressure
- Prefer established repo names over generic synonyms.
- If a change concerns user data, say language project, not just project.
- If a change concerns the source tree, say repo, worktree, or the specific build/test project.
- If a change touches synchronization, distinguish the user concept (Send/Receive) from the implementation/tooling concept (FLEx Bridge) unless the distinction is intentionally irrelevant.
- If a change touches the managed/native boundary, call out ViewsInterfaces, Views, FwKernel, or registration-free COM explicitly.
- Test classes follow
<Subject>Testsnaming. Test methods use plain descriptive English with the structureMethodUnderTest_ExpectedResultorMethodUnderTest_ExpectedResult_WhenCondition— examples:GetGuidForJumpToTool_UsesRootObject_WhenNoCurrentSlice,GetWheelScrollPixels_UsesSystemWheelSettings,TryGetWheelScrollPosition_ReturnsFalse_WhenAlreadyAtTop. Only nested classes inside test fixtures for mock/helper types.
Review Workflow Language
- PR preflight: An interactive branch-readiness workflow before posting or updating a PR. It applies FieldWorks review policy, may use specialist review agents, interviews the author about risks and validation, and writes
.review/summary.md. - Review analyzer: The FieldWorks review policy in
.github/instructions/review-analyzer.instructions.md. It defines what to check; it is not the interactive workflow. - Specialist review agent: A focused read-only reviewer such as the FieldWorks C#, WinForms, C++, or Avalonia agent. Specialist output is evidence for the final synthesis, not a replacement for verifying findings against code.
- Review comment: Any actionable feedback from Copilot or a human reviewer on a pull request.
- Review thread: A GitHub inline conversation anchored to code. Resolve only after the thread is fully addressed and no question remains.
- Copilot reviewer comment: Automated review feedback from GitHub Copilot. Evaluate it like external reviewer feedback; do not treat it as authoritative without checking the code.
- Human reviewer comment: Feedback from a person. Treat it seriously, but still verify the requested change against FieldWorks conventions and existing behavior.
- Sensible fix: A reviewer request that is technically sound, unambiguous, scoped, and compatible with repo rules.
- Ambiguous feedback: A reviewer request that lacks enough context, conflicts with another requirement, or would require a product or architecture decision. Ask the user before changing code.
- Reply: A response in the review conversation explaining a fix, asking a question, or giving technical reasoning for no code change.
- Resolve: Marking a review thread addressed in GitHub. Do this only after the code or reply fully answers the thread.
Remaining Open Question
- Should this root file stay mixed product-plus-architecture, or should lower-level developer terms move into narrower subtree contexts later?
ADR Candidates
- No repository-wide ADR location is established yet.
- If a terminology decision becomes hard to reverse or affects naming across many files, record it here first and promote it to a formal ADR only if the repo adopts a dedicated ADR convention.