Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ Bin/ilrepack-assemblies -whitespace
*.json -whitespace
*.js -whitespace
Src/LexText/ParserCore/ParserCoreTests/**/*.txt -whitespace

# Verify snapshot testing
*.verified.png binary
*.received.png binary
5 changes: 5 additions & 0 deletions .github/instructions/build.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ This file documents the **supported** build workflow for FieldWorks.

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

## Non-Windows hosts
- Linux and macOS are supported for editing, code search, documentation, specs, and agent workflows only.
- Do not attempt to build, test, or run installer/setup flows on non-Windows hosts.
- `build.ps1` and `test.ps1` intentionally fail fast on non-Windows hosts so automation notices the environment mismatch.

## Quick start (PowerShell)
```powershell
# Full traversal build (Debug/x64 defaults)
Expand Down
72 changes: 72 additions & 0 deletions .github/instructions/csharp.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
description: 'Guidelines for building C# applications'
applyTo: '**/*.cs'
---

# C# Development

## Scope
- FieldWorks managed code is a Windows desktop codebase built on .NET Framework 4.8 and native dependencies.
- Treat this file as guidance for existing FieldWorks C# projects, not for ASP.NET or service-oriented .NET applications.
- On Linux and macOS, limit work to editing, search, docs, and specs. Do not claim to have built or run managed binaries there.

## Language Version And Features
- Use the repo default C# language version unless a project explicitly overrides it. Today that default is C# 8.0 via `Directory.Build.props`.
- Do not introduce C# features that require a newer language version without first updating repo-wide build policy.
- Nullable reference types are disabled by default. Only use nullable annotations and nullable-flow assumptions in projects that opt in explicitly.
- Prefer syntax that is already common in the touched area. Consistency with nearby code is more important than using the newest available syntax.

## General Instructions
- Make only high-confidence suggestions when reviewing code changes.
- Fix the root cause when practical, but keep edits narrow and compatible with existing behavior.
- Handle edge cases and exception paths explicitly. Do not swallow exceptions without a documented reason.
- Treat native interop, COM, registry-free COM, file formats, and serialization boundaries as high-risk areas that need extra care.

## Naming Conventions
- Follow PascalCase for types, methods, properties, events, and public members.
- Use camelCase for locals and private fields.
- Prefix interfaces with `I`.
- Keep namespaces aligned with the existing project root namespace instead of inventing new top-level naming schemes.

## Formatting And Style
- Apply the formatting rules defined in `.editorconfig` and match surrounding code.
- Prefer block-scoped namespaces. Do not default to file-scoped namespaces in this repo.
- Keep using directives simple and consistent with the file you are editing.
- Use `nameof` instead of string literals when referencing member names.
- Use pattern matching where it improves clarity and is supported by the project language version. Do not force newer syntax into older-looking code.

## Documentation And Comments
- Public APIs should have XML documentation comments.
- Add code comments only when intent, invariants, or interop constraints are not obvious from the code itself.
- Do not add boilerplate comments to every method.

## Project Conventions
- Most managed projects here are SDK-style `.csproj` files targeting `net48`.
- Keep `GenerateAssemblyInfo` disabled where the project relies on linked `CommonAssemblyInfo.cs`.
- Preserve project-specific build settings such as warnings-as-errors, x64 assumptions, WinExe/WindowsDesktop settings, and registration-free COM behavior.
- When adding new files, update the project file only if the specific project format requires it.

## Desktop, UI, And Localization
- FieldWorks is a desktop application. Favor guidance relevant to WinForms, WPF, dialogs, view models, threading, and long-running UI work.
- UI-affecting code must respect the UI thread. Avoid blocking calls that can freeze the application.
- Keep user-visible strings in `.resx` resources and follow existing localization patterns. Do not hardcode new UI strings.
- Preserve designer compatibility for WinForms and avoid edits that break generated code patterns.

## Nullability And Defensive Code
- Because nullable reference types are usually disabled, write explicit null checks at public entry points and interop boundaries when required by the surrounding code.
- Prefer `is null` and `is not null` checks when adding new null checks.
- Do not pretend the compiler will enforce null-state safety unless the project has opted into nullable analysis.

## Testing
- For behavior changes and bug fixes, add or update tests when practical.
- Follow nearby test naming and structure conventions. Do not add `Arrange`, `Act`, or `Assert` comments unless the existing file already uses them.
- Prefer fast, deterministic NUnit tests for managed code.
- 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.

## Build And Validation
- Use `./build.ps1` for builds and `./test.ps1` for tests in normal repo workflows.
- Avoid changing build, packaging, COM, or registry behavior without checking the existing build instructions and affected tests.
- Treat compiler warnings as actionable unless the repo already documents a specific exception.

## What Not To Assume
- 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.
4 changes: 2 additions & 2 deletions .github/instructions/debugging.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ description: "Runtime debugging and tracing guidance for FieldWorks"

## Dev switch (auto config)
- FieldWorks now supports a swappable diagnostics config via `FieldWorks.Diagnostics.config`.
- 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.
- 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.
- Dev log location: `Output/Debug/FieldWorks.trace.log` (relative to the app folder) so it’s easy to collect alongside binaries.
- 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.

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

## Proposed Improvements (dev-only)
- Add `Docs/FieldWorks.trace.sample.config` with the snippet above for easy reuse.
- 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.
- Keep `build.ps1 -EnableTracing` as the single scripted path that copies the dev diagnostics file next to `FieldWorks.exe` for local trace-enabled runs.
- Document standard trace switches in `Docs/logging.md` and keep `EnvVarTraceListener` as the default listener for dev traces.
81 changes: 45 additions & 36 deletions .github/instructions/dotnet-framework.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,46 @@ applyTo: '**/*.csproj, **/*.cs'
# .NET Framework Development

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

## Project File Management

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

- **Explicit File Inclusion**: All new source files **MUST** be explicitly added to the project file (`.csproj`) using a `<Compile>` element
- .NET Framework projects do not automatically include files in the directory like SDK-style projects
- Example: `<Compile Include="Path\To\NewFile.cs" />`
- **Implicit file inclusion is common**: SDK-style projects usually include new `.cs` files automatically.
- **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.
- **Assembly metadata is managed explicitly**: Keep `GenerateAssemblyInfo` disabled where the project links `CommonAssemblyInfo.cs`.
- **Preserve project-specific settings**: Keep existing settings for x64, WinExe, WindowsDesktop, COM, resources, warnings-as-errors, and custom MSBuild targets.

- **No Implicit Imports**: Unlike SDK-style projects, .NET Framework projects do not automatically import common namespaces or assemblies

- **Build Configuration**: Contains explicit `<PropertyGroup>` sections for Debug/Release configurations
- **Do not normalize projects unnecessarily**: Avoid converting project structure, import style, or target declarations unless that is the task.

- **Output Paths**: Explicit `<OutputPath>` and `<IntermediateOutputPath>` definitions

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

## NuGet Package Management
- 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.
- 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.
- When recommending NuGet packages, ensure they are compatible with .NET Framework or .NET Standard 2.0 (not only .NET Core or .NET 5+).

## C# Language Version is 7.3
- This project is limited to C# 7.3 features only. Please avoid using:
## C# Language Version
- The repo-wide default language version for C# projects is 8.0.
- Do not introduce features that require a newer language version unless the specific project or repo policy is updated first.
- Prefer syntax already used in the touched area so edits remain consistent with surrounding code.

### C# 8.0 features available by default
- Switch expressions and pattern matching enhancements.
- Using declarations where disposal scope remains clear.
- Null-coalescing assignment and range/index operators when they improve clarity.

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

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

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

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

## Common .NET Framework Pitfalls and Best Practices

### Async/Await Patterns
- **ConfigureAwait(false)**: Always use `ConfigureAwait(false)` in library code to avoid deadlocks:
- **ConfigureAwait(false)**: Use it deliberately in library or background code when you do not need to resume on the UI thread:
```csharp
var result = await SomeAsyncMethod().ConfigureAwait(false);
```
- **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.
- **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.
- **Respect the UI thread**: Do not move UI-bound code onto background threads or block the UI while waiting on long-running work.

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

### Resources and localization
- Put user-visible strings into `.resx` resources and follow existing localization patterns.
- Avoid hardcoding new UI strings in C# code.

### Interop and COM
- Treat P/Invoke, COM, registration-free COM, and serialization boundaries as high risk.
- Preserve existing manifest, marshaling, and build settings unless the task explicitly requires changing them.

### Performance Considerations
- **Avoid boxing**: Be aware of boxing/unboxing with value types and generics
- **String interning**: Use `string.Intern()` judiciously for frequently used strings
Expand Down
3 changes: 0 additions & 3 deletions .github/instructions/repo.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@ Provide clear, concise, and enforceable rules that help AI coding agents and aut
## Rules (high-impact, short)
- Prefer the repository top-level build (`.\build.ps1`) and solution (`FieldWorks.sln`) for full builds.
- Keep localization consistent: use `.resx` and follow `crowdin.json` for crowdin integration.
- Before commit/push, run the existing VS Code task `CI: Full local check`.
- After rebase/merge/cherry-pick conflict resolution, run `CI: Whitespace check`; if it fixes files, restage them and rerun.
- When rewriting history or adding commits, run `CI: Commit messages` before pushing.
2 changes: 0 additions & 2 deletions .github/instructions/terminal.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ Placement policy for wrappers:

**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.

**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.

## Transformations

| ❌ Blocked | ✅ Use Instead |
Expand Down
4 changes: 2 additions & 2 deletions .github/prompts/opsx-archive.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Archive a completed change in the experimental workflow.
- If changes needed: "Sync now (recommended)", "Archive without syncing"
- If already synced: "Archive now", "Sync anyway", "Cancel"

If user chooses sync, execute `/opsx:sync` logic. Proceed to archive regardless of choice.
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.

5. **Perform the archive**

Expand Down Expand Up @@ -150,5 +150,5 @@ Target archive directory already exists.
- Don't block archive on warnings - just inform and confirm
- Preserve .openspec.yaml when moving to archive (it moves with the directory)
- Show clear summary of what happened
- If sync is requested, use /opsx:sync approach (agent-driven)
- If sync is requested, use the Skill tool to invoke `openspec-sync-specs` (agent-driven)
- If delta specs exist, always run the sync assessment and show the combined summary before prompting
2 changes: 1 addition & 1 deletion .github/prompts/opsx-bulk-archive.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Failed K changes:
```
## No Changes to Archive

No active changes found. Use `/opsx:new` to create a new change.
No active changes found. Create a new change to get started.
```

**Guardrails**
Expand Down
7 changes: 3 additions & 4 deletions .github/prompts/opsx-explore.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Enter explore mode - think through ideas, investigate problems, cla

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

**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.
**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.

**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.

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

Think freely. When insights crystallize, you might offer:

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

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

There's no required ending. Discovery might:

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