Skip to content

Commit f403514

Browse files
committed
perf(render): optimize views rendering
- speed up DataTree and Views rendering, scrolling, and layout work - expand render benchmarks, committed baselines, and timing coverage - keep timing baselines informational in CI and harden test runs - refresh build, tracing, and supporting test infrastructure
1 parent b6ac397 commit f403514

403 files changed

Lines changed: 43185 additions & 533821 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ Bin/ilrepack-assemblies -whitespace
3131
*.json -whitespace
3232
*.js -whitespace
3333
Src/LexText/ParserCore/ParserCoreTests/**/*.txt -whitespace
34+
35+
# Verify snapshot testing
36+
*.verified.png binary
37+
*.received.png binary

.github/instructions/build.instructions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ This file documents the **supported** build workflow for FieldWorks.
1010

1111
FieldWorks is **Windows-first** and **x64-only**. Use the repo scripts so build ordering (native before managed) is correct.
1212

13+
## Non-Windows hosts
14+
- Linux and macOS are supported for editing, code search, documentation, specs, and agent workflows only.
15+
- Do not attempt to build, test, or run installer/setup flows on non-Windows hosts.
16+
- `build.ps1` and `test.ps1` intentionally fail fast on non-Windows hosts so automation notices the environment mismatch.
17+
1318
## Quick start (PowerShell)
1419
```powershell
1520
# Full traversal build (Debug/x64 defaults)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
description: 'Guidelines for building C# applications'
3+
applyTo: '**/*.cs'
4+
---
5+
6+
# C# Development
7+
8+
## Scope
9+
- FieldWorks managed code is a Windows desktop codebase built on .NET Framework 4.8 and native dependencies.
10+
- Treat this file as guidance for existing FieldWorks C# projects, not for ASP.NET or service-oriented .NET applications.
11+
- On Linux and macOS, limit work to editing, search, docs, and specs. Do not claim to have built or run managed binaries there.
12+
13+
## Language Version And Features
14+
- Use the repo default C# language version unless a project explicitly overrides it. Today that default is C# 8.0 via `Directory.Build.props`.
15+
- Do not introduce C# features that require a newer language version without first updating repo-wide build policy.
16+
- Nullable reference types are disabled by default. Only use nullable annotations and nullable-flow assumptions in projects that opt in explicitly.
17+
- Prefer syntax that is already common in the touched area. Consistency with nearby code is more important than using the newest available syntax.
18+
19+
## General Instructions
20+
- Make only high-confidence suggestions when reviewing code changes.
21+
- Fix the root cause when practical, but keep edits narrow and compatible with existing behavior.
22+
- Handle edge cases and exception paths explicitly. Do not swallow exceptions without a documented reason.
23+
- Treat native interop, COM, registry-free COM, file formats, and serialization boundaries as high-risk areas that need extra care.
24+
25+
## Naming Conventions
26+
- Follow PascalCase for types, methods, properties, events, and public members.
27+
- Use camelCase for locals and private fields.
28+
- Prefix interfaces with `I`.
29+
- Keep namespaces aligned with the existing project root namespace instead of inventing new top-level naming schemes.
30+
31+
## Formatting And Style
32+
- Apply the formatting rules defined in `.editorconfig` and match surrounding code.
33+
- Prefer block-scoped namespaces. Do not default to file-scoped namespaces in this repo.
34+
- Keep using directives simple and consistent with the file you are editing.
35+
- Use `nameof` instead of string literals when referencing member names.
36+
- Use pattern matching where it improves clarity and is supported by the project language version. Do not force newer syntax into older-looking code.
37+
38+
## Documentation And Comments
39+
- Public APIs should have XML documentation comments.
40+
- Add code comments only when intent, invariants, or interop constraints are not obvious from the code itself.
41+
- Do not add boilerplate comments to every method.
42+
43+
## Project Conventions
44+
- Most managed projects here are SDK-style `.csproj` files targeting `net48`.
45+
- Keep `GenerateAssemblyInfo` disabled where the project relies on linked `CommonAssemblyInfo.cs`.
46+
- Preserve project-specific build settings such as warnings-as-errors, x64 assumptions, WinExe/WindowsDesktop settings, and registration-free COM behavior.
47+
- When adding new files, update the project file only if the specific project format requires it.
48+
49+
## Desktop, UI, And Localization
50+
- FieldWorks is a desktop application. Favor guidance relevant to WinForms, WPF, dialogs, view models, threading, and long-running UI work.
51+
- UI-affecting code must respect the UI thread. Avoid blocking calls that can freeze the application.
52+
- Keep user-visible strings in `.resx` resources and follow existing localization patterns. Do not hardcode new UI strings.
53+
- Preserve designer compatibility for WinForms and avoid edits that break generated code patterns.
54+
55+
## Nullability And Defensive Code
56+
- Because nullable reference types are usually disabled, write explicit null checks at public entry points and interop boundaries when required by the surrounding code.
57+
- Prefer `is null` and `is not null` checks when adding new null checks.
58+
- Do not pretend the compiler will enforce null-state safety unless the project has opted into nullable analysis.
59+
60+
## Testing
61+
- For behavior changes and bug fixes, add or update tests when practical.
62+
- Follow nearby test naming and structure conventions. Do not add `Arrange`, `Act`, or `Assert` comments unless the existing file already uses them.
63+
- Prefer fast, deterministic NUnit tests for managed code.
64+
- Use `./test.ps1` on Windows to run tests, and `./build.ps1` when you need a supporting build first. Do not recommend ad-hoc `dotnet test` or `msbuild` commands as the normal path for this repo.
65+
66+
## Build And Validation
67+
- Use `./build.ps1` for builds and `./test.ps1` for tests in normal repo workflows.
68+
- Avoid changing build, packaging, COM, or registry behavior without checking the existing build instructions and affected tests.
69+
- Treat compiler warnings as actionable unless the repo already documents a specific exception.
70+
71+
## What Not To Assume
72+
- Do not assume ASP.NET Core, Minimal APIs, Entity Framework Core, Swagger/OpenAPI, cloud deployment, container publishing, or JWT authentication are relevant unless the user is explicitly working in a repo area that adds those technologies.

.github/instructions/debugging.instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ description: "Runtime debugging and tracing guidance for FieldWorks"
4949

5050
## Dev switch (auto config)
5151
- FieldWorks now supports a swappable diagnostics config via `FieldWorks.Diagnostics.config`.
52-
- Default is quiet. `build.ps1` now enables the dev diagnostics config automatically for Debug builds unless you override `/p:UseDevTraceConfig`. You can also force it via `UseDevTraceConfig=true`, by setting environment variable `FW_TRACE_LOG` before the build, or by passing `-TraceCrashes` to `build.ps1`; the dev diagnostics file is copied as `FieldWorks.Diagnostics.config` in the output.
52+
- Default is quiet. Use `build.ps1 -EnableTracing` to copy the dev diagnostics file into the output as `FieldWorks.Diagnostics.config`. You can also force it via `UseDevTraceConfig=true` or by setting environment variable `FW_TRACE_LOG` before the build.
5353
- Dev log location: `Output/Debug/FieldWorks.trace.log` (relative to the app folder) so it’s easy to collect alongside binaries.
5454
- Dev config logs to `%temp%/FieldWorks.trace.log` and turns on the core switches above. Edit `Src/Common/FieldWorks/FieldWorks.Diagnostics.dev.config` to change log path or switches.
5555

@@ -59,5 +59,5 @@ description: "Runtime debugging and tracing guidance for FieldWorks"
5959

6060
## Proposed Improvements (dev-only)
6161
- Add `Docs/FieldWorks.trace.sample.config` with the snippet above for easy reuse.
62-
- Introduce a dev flag (`UseDevTraceConfig=true` or `FW_TRACE_LOG` env var) that copies the dev diagnostics file next to `FieldWorks.exe` in Debug builds so tracing is on by default for local runs.
62+
- Keep `build.ps1 -EnableTracing` as the single scripted path that copies the dev diagnostics file next to `FieldWorks.exe` for local trace-enabled runs.
6363
- Document standard trace switches in `Docs/logging.md` and keep `EnvVarTraceListener` as the default listener for dev traces.

.github/instructions/dotnet-framework.instructions.md

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,44 +6,46 @@ applyTo: '**/*.csproj, **/*.cs'
66
# .NET Framework Development
77

88
## Build and Compilation Requirements
9-
- Always use `msbuild /t:rebuild` to build the solution or projects instead of `dotnet build`
9+
- Use `./build.ps1` for normal builds and `./test.ps1` for normal test runs.
10+
- Do not use `dotnet build` for the main repo workflow.
11+
- Avoid direct `msbuild` or project-only builds unless you are explicitly debugging build infrastructure.
1012

1113
## Project File Management
1214

13-
### Non-SDK Style Project Structure
14-
.NET Framework projects use the legacy project format, which differs significantly from modern SDK-style projects:
15+
### SDK-style net48 projects are common
16+
Most managed projects in this repo use SDK-style `.csproj` files while still targeting `.NET Framework` `net48`.
1517

16-
- **Explicit File Inclusion**: All new source files **MUST** be explicitly added to the project file (`.csproj`) using a `<Compile>` element
17-
- .NET Framework projects do not automatically include files in the directory like SDK-style projects
18-
- Example: `<Compile Include="Path\To\NewFile.cs" />`
18+
- **Implicit file inclusion is common**: SDK-style projects usually include new `.cs` files automatically.
19+
- **Check the touched project before editing**: Some projects still carry explicit includes, linked files, designer items, generated code, or custom metadata that must be preserved.
20+
- **Assembly metadata is managed explicitly**: Keep `GenerateAssemblyInfo` disabled where the project links `CommonAssemblyInfo.cs`.
21+
- **Preserve project-specific settings**: Keep existing settings for x64, WinExe, WindowsDesktop, COM, resources, warnings-as-errors, and custom MSBuild targets.
1922

20-
- **No Implicit Imports**: Unlike SDK-style projects, .NET Framework projects do not automatically import common namespaces or assemblies
21-
22-
- **Build Configuration**: Contains explicit `<PropertyGroup>` sections for Debug/Release configurations
23+
- **Do not normalize projects unnecessarily**: Avoid converting project structure, import style, or target declarations unless that is the task.
2324

24-
- **Output Paths**: Explicit `<OutputPath>` and `<IntermediateOutputPath>` definitions
25-
26-
- **Target Framework**: Uses `<TargetFrameworkVersion>` instead of `<TargetFramework>`
27-
- Example: `<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>`
25+
### Legacy project caveat
26+
Some non-SDK-style or tool-specific projects may still exist. When you encounter one:
27+
- Keep explicit `<Compile Include=... />` items and other legacy structure intact.
28+
- Update the project file only as much as the change requires.
29+
- Do not assume you can migrate it to SDK-style as part of routine code edits.
2830

2931
## NuGet Package Management
3032
- Installing and updating NuGet packages in .NET Framework projects is a complex task requiring coordinated changes to multiple files. Therefore, **do not attempt to install or update NuGet packages** in this project.
3133
- Instead, if changes to NuGet references are required, ask the user to install or update NuGet packages using the Visual Studio NuGet Package Manager or Visual Studio package manager console.
3234
- When recommending NuGet packages, ensure they are compatible with .NET Framework or .NET Standard 2.0 (not only .NET Core or .NET 5+).
3335

34-
## C# Language Version is 7.3
35-
- This project is limited to C# 7.3 features only. Please avoid using:
36+
## C# Language Version
37+
- The repo-wide default language version for C# projects is 8.0.
38+
- Do not introduce features that require a newer language version unless the specific project or repo policy is updated first.
39+
- Prefer syntax already used in the touched area so edits remain consistent with surrounding code.
40+
41+
### C# 8.0 features available by default
42+
- Switch expressions and pattern matching enhancements.
43+
- Using declarations where disposal scope remains clear.
44+
- Null-coalescing assignment and range/index operators when they improve clarity.
3645

37-
### C# 8.0+ Features (NOT SUPPORTED):
38-
- Using declarations (`using var stream = ...`)
39-
- Await using statements (`await using var resource = ...`)
40-
- Switch expressions (`variable switch { ... }`)
41-
- Null-coalescing assignment (`??=`)
42-
- Range and index operators (`array[1..^1]`, `array[^1]`)
43-
- Default interface methods
44-
- Readonly members in structs
45-
- Static local functions
46-
- Nullable reference types (`string?`, `#nullable enable`)
46+
### Features not safe to assume repo-wide
47+
- Nullable reference types are not enabled repo-wide. Do not introduce `string?`, `#nullable enable`, or nullable-flow assumptions unless the project explicitly opts in.
48+
- File-scoped namespaces are not available under the repo default language version and should not be introduced.
4749

4850
### C# 9.0+ Features (NOT SUPPORTED):
4951
- Records (`public record Person(string Name)`)
@@ -58,26 +60,25 @@ applyTo: '**/*.csproj, **/*.cs'
5860
- Record structs
5961
- Required members
6062

61-
### Use Instead (C# 7.3 Compatible):
62-
- Traditional using statements with braces
63-
- Switch statements instead of switch expressions
64-
- Explicit null checks instead of null-coalescing assignment
65-
- Array slicing with manual indexing
66-
- Abstract classes or interfaces instead of default interface methods
63+
### Use instead when staying within repo defaults
64+
- Block-scoped namespaces
65+
- Explicit null checks unless the project has enabled nullable analysis
66+
- Established project patterns over newer syntax for its own sake
6767

6868
## Environment Considerations (Windows environment)
69-
- Use Windows-style paths with backslashes (e.g., `C:\path\to\file.cs`)
70-
- Use Windows-appropriate commands when suggesting terminal operations
71-
- Consider Windows-specific behaviors when working with file system operations
69+
- FieldWorks builds and managed test runs are Windows-only.
70+
- On non-Windows hosts, limit work to editing, code search, docs, and specs.
71+
- When suggesting build or test commands, prefer the repo PowerShell scripts and Windows-oriented workflows.
7272

7373
## Common .NET Framework Pitfalls and Best Practices
7474

7575
### Async/Await Patterns
76-
- **ConfigureAwait(false)**: Always use `ConfigureAwait(false)` in library code to avoid deadlocks:
76+
- **ConfigureAwait(false)**: Use it deliberately in library or background code when you do not need to resume on the UI thread:
7777
```csharp
7878
var result = await SomeAsyncMethod().ConfigureAwait(false);
7979
```
80-
- **Avoid sync-over-async**: Don't use `.Result` or `.Wait()` or `.GetAwaiter().GetResult()`. These sync-over-async patterns can lead to deadlocks and poor performance. Always use `await` for asynchronous calls.
80+
- **Avoid sync-over-async**: Don't use `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()` unless you have a clear, reviewed reason. These patterns can deadlock desktop UI code.
81+
- **Respect the UI thread**: Do not move UI-bound code onto background threads or block the UI while waiting on long-running work.
8182

8283
### DateTime Handling
8384
- **Use DateTimeOffset for timestamps**: Prefer `DateTimeOffset` over `DateTime` for absolute time points
@@ -106,6 +107,14 @@ applyTo: '**/*.csproj, **/*.cs'
106107
- **Don't swallow exceptions**: Always log or re-throw exceptions appropriately
107108
- **Use using for disposable resources**: Ensures proper cleanup even when exceptions occur
108109

110+
### Resources and localization
111+
- Put user-visible strings into `.resx` resources and follow existing localization patterns.
112+
- Avoid hardcoding new UI strings in C# code.
113+
114+
### Interop and COM
115+
- Treat P/Invoke, COM, registration-free COM, and serialization boundaries as high risk.
116+
- Preserve existing manifest, marshaling, and build settings unless the task explicitly requires changing them.
117+
109118
### Performance Considerations
110119
- **Avoid boxing**: Be aware of boxing/unboxing with value types and generics
111120
- **String interning**: Use `string.Intern()` judiciously for frequently used strings

.github/instructions/repo.instructions.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,3 @@ Provide clear, concise, and enforceable rules that help AI coding agents and aut
1212
## Rules (high-impact, short)
1313
- Prefer the repository top-level build (`.\build.ps1`) and solution (`FieldWorks.sln`) for full builds.
1414
- Keep localization consistent: use `.resx` and follow `crowdin.json` for crowdin integration.
15-
- Before commit/push, run the existing VS Code task `CI: Full local check`.
16-
- After rebase/merge/cherry-pick conflict resolution, run `CI: Whitespace check`; if it fixes files, restage them and rerun.
17-
- When rewriting history or adding commits, run `CI: Commit messages` before pushing.

.github/instructions/terminal.instructions.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ Placement policy for wrappers:
1313

1414
**MCP-first:** When the `ps-tools` MCP server is running, prefer MCP tools (`Git-Search`, `Read-FileContent`, `Invoke-AgentTask`, `build`, `test`, agent tools) instead of direct terminal commands. Use wrappers only when MCP is unavailable.
1515

16-
**Task-first for CI parity:** Prefer the existing VS Code tasks `CI: Whitespace check`, `CI: Commit messages`, and `CI: Full local check` over ad-hoc shell commands. These tasks are already allowed for agent use and match the repository CI checks.
17-
1816
## Transformations
1917

2018
| ❌ Blocked | ✅ Use Instead |

.github/prompts/opsx-archive.prompt.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Archive a completed change in the experimental workflow.
5656
- If changes needed: "Sync now (recommended)", "Archive without syncing"
5757
- If already synced: "Archive now", "Sync anyway", "Cancel"
5858

59-
If user chooses sync, execute `/opsx:sync` logic. Proceed to archive regardless of choice.
59+
If user chooses sync, use Task tool (subagent_type: "general-purpose", prompt: "Use Skill tool to invoke openspec-sync-specs for change '<name>'. Delta spec analysis: <include the analyzed delta spec summary>"). Proceed to archive regardless of choice.
6060

6161
5. **Perform the archive**
6262

@@ -150,5 +150,5 @@ Target archive directory already exists.
150150
- Don't block archive on warnings - just inform and confirm
151151
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
152152
- Show clear summary of what happened
153-
- If sync is requested, use /opsx:sync approach (agent-driven)
153+
- If sync is requested, use the Skill tool to invoke `openspec-sync-specs` (agent-driven)
154154
- If delta specs exist, always run the sync assessment and show the combined summary before prompting

.github/prompts/opsx-bulk-archive.prompt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ Failed K changes:
222222
```
223223
## No Changes to Archive
224224

225-
No active changes found. Use `/opsx:new` to create a new change.
225+
No active changes found. Create a new change to get started.
226226
```
227227
228228
**Guardrails**

.github/prompts/opsx-explore.prompt.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Enter explore mode - think through ideas, investigate problems, cla
44

55
Enter explore mode. Think deeply. Visualize freely. Follow the conversation wherever it goes.
66

7-
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first (e.g., start a change with `/opsx:new` or `/opsx:ff`). You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.
7+
**IMPORTANT: Explore mode is for thinking, not implementing.** You may read files, search code, and investigate the codebase, but you must NEVER write code or implement features. If the user asks you to implement something, remind them to exit explore mode first and create a change proposal. You MAY create OpenSpec artifacts (proposals, designs, specs) if the user asks—that's capturing thinking, not implementing.
88

99
**This is a stance, not a workflow.** There are no fixed steps, no required sequence, no mandatory outputs. You're a thinking partner helping the user explore.
1010

@@ -97,8 +97,7 @@ If the user mentioned a specific change name, read its artifacts for context.
9797

9898
Think freely. When insights crystallize, you might offer:
9999

100-
- "This feels solid enough to start a change. Want me to create one?"
101-
→ Can transition to `/opsx:new` or `/opsx:ff`
100+
- "This feels solid enough to start a change. Want me to create a proposal?"
102101
- Or keep exploring - no pressure to formalize
103102

104103
### When a change exists
@@ -150,7 +149,7 @@ If the user mentions a change or you detect one is relevant:
150149

151150
There's no required ending. Discovery might:
152151

153-
- **Flow into action**: "Ready to start? `/opsx:new` or `/opsx:ff`"
152+
- **Flow into a proposal**: "Ready to start? I can create a change proposal."
154153
- **Result in artifact updates**: "Updated design.md with these decisions"
155154
- **Just provide clarity**: User has what they need, moves on
156155
- **Continue later**: "We can pick this up anytime"

0 commit comments

Comments
 (0)