Compare commits

...
41 Commits
Author SHA1 Message Date
akritikos 1912484334 🔧 Updates GitVersion configuration to enhance branch management and increment strategies 2026-10-27 20:57:46 +02:00
akritikos f4c843b9f7 🔧 Updates C# documentation guidelines for comments and logging practices 2026-09-07 22:00:11 +03:00
akritikos eee54a4a36 🔥 Removes increment prevention on merges
It suppresses the increment that a merged feature/hotfix branch contributes, freezing main's version on every merge.
2026-08-30 03:07:54 +03:00
akritikos 70a0eeec33 📌 Switches versioning to trunk-based development 2026-08-30 02:38:40 +03:00
akritikos 3b31cbcb14 📌 Updates versioning calculation 2026-08-30 02:29:30 +03:00
akritikos 0d7d18fae0 🔧 Sanitizes assembly names 2026-08-28 23:35:14 +03:00
akritikos 243a3ce519 🔧 Replaces ineffective merge drivers with EOL normalisation
merge=upstream-wins named a driver that is not built in and is not
defined in any git config, so git silently fell back to the default
3-way merge. Custom merge drivers live in .git/config and cannot be
distributed via .gitattributes, so downstream clones never had it.

merge=union on Directory.Packages.props silently produced duplicate
PackageVersion entries when both sides changed the same Include,
which NuGet rejects at build time with no conflict to review.

No tracked blob is stored with CRLF, so text=auto is a no-op for
existing content and only guards future contributions.
2026-08-28 20:10:29 +03:00
akritikos f975b7a41f 📝 Documents changelog generation in the release skill 2026-08-28 20:08:42 +03:00
akritikos be09aef8a3 📌 Aligns versioning to GitHubFlow 2026-08-27 19:12:47 +03:00
akritikos 406af21694 🚨 Removes documentation hard requirement from samples & tests 2026-08-27 05:18:38 +03:00
akritikos d7b610d6f5 🙈 Excludes Copilot tracking folder (HVE R-P-I loop) 2026-08-26 23:17:26 +03:00
akritikos 4d05e08d98 🚚 Copies OpenAPI Documents for automated generation of API Clients using Refitter 2026-08-26 23:17:04 +03:00
akritikos fdbf44149a 🔖 Adds seperate versioning instructions to release skill 2026-08-26 22:48:23 +03:00
akritikos 88b3e5c661 🧱 Ensures changelog file is generated before packing 2026-08-26 22:45:56 +03:00
akritikos 96696ab2bb 📌 Allows each library to maintain their own version 2026-08-26 22:45:23 +03:00
akritikos 569fdd8053 🗑️ Disables versioned hierarchical nuget output 2026-08-26 22:38:18 +03:00
akritikos 5f7dc55e66 🔧 Updates copilot instructions 2026-08-26 22:38:18 +03:00
akritikos 661908bcea 🔧 Moves CLS Compliance to target file so it can be evaluated 2026-08-26 22:38:18 +03:00
akritikos 9b27bbdc37 ⬆️ Updates template dependencies 2026-08-26 22:38:17 +03:00
akritikos 7bc86d8a34 🔧 Ensures OpenAPI documents are named consistently 2026-08-26 22:38:17 +03:00
akritikos 4095d6385b 🚨 Sanitizes warnings 2026-08-26 22:38:17 +03:00
akritikos bd50907471 🤖 Adds some more strict rails for handling .NET projects 2026-08-26 22:38:16 +03:00
akritikos eea4ce7a0e ✨ Updates API, C#, Docker, MSBuild, and Testing guidelines
Refines conventions for ASP.NET API endpoints, C# documentation,
Docker build arguments, MSBuild package management, and testing
method naming and structure. These changes aim to enhance clarity
and enforce best practices across the codebase.
2026-08-26 22:38:16 +03:00
akritikos b169a233ed 🔧 Removes default internals visibility for test projects
Eliminates the automatic exposure of assembly internals to
test projects when no friend assemblies are declared,
streamlining the handling of internals visibility.
2026-08-26 22:38:16 +03:00
akritikos b34dffe5f2 ✨ Removes double-BOM 2026-08-26 22:38:16 +03:00
akritikos 5d109c31aa 🚨 Update .editorconfig and .globalconfig for improved C# coding standards
Refactor coding conventions in .editorconfig and .globalconfig to
enhance code quality and maintainability. This includes organizing
usings, modifying naming conventions, and adjusting various C#
style preferences.
2026-08-26 22:38:15 +03:00
akritikosandCopilot 0cc34f7b4b ✨ Add skills for EF migrations and new ADR creation
Introduces new skills for managing Entity Framework Core migrations
and creating Architectural Decision Records (ADRs). These skills
provide structured guidance for users to document architectural
decisions and manage database migrations effectively.

Co-authored-by: Copilot <copilot@github.com>
2026-08-26 22:38:15 +03:00
akritikos f5ce51d854 ✨ Adds new prompts for auditing, converting controllers, and logging
Introduces several new markdown prompt files to enhance the
repository's capabilities. These include instructions for auditing
files, converting MVC controllers to Minimal API endpoints, and
refactoring inline logger calls to use LoggerMessage-generated
methods. This improves code quality and aligns with project
conventions.
2026-08-26 22:38:15 +03:00
akritikosandCopilot 0f5eab59a8 ✨ Adds documentation instructions for ADR, analyzers, and observability
Introduces new markdown files detailing editing rules for ADRs,
guidelines for analyzer and style configuration, and best practices
for observability and feature flags. These documents aim to ensure
consistency and clarity in project documentation and code quality.

Co-authored-by: Copilot <copilot@github.com>
2026-08-26 22:38:15 +03:00
akritikos 57062f7bea 📝 Updates C# and MSBuild instructions for clarity 2026-08-26 22:38:14 +03:00
akritikos c80a6fbe58 📝 Updates generic copilot instructions 2026-08-26 22:38:14 +03:00
akritikos 14f84c0300 ✨ Adds project guidelines and conventions for Github Copilot
Introduces detailed instructions for ASP.NET API, C#, Docker, MSBuild,
testing, and library creation. These guidelines aim to standardize
development practices and improve code quality across the project.
2026-08-26 22:38:14 +03:00
akritikos 741b2f0501 ✨ Adds VSCode configuration files for extensions and settings
Introduces new extensions.json and settings.json files to recommend
useful VSCode extensions and configure JSON schemas, word wrap, and
default formatters for XML files. This enhances the development
environment for better productivity and consistency.
2026-08-26 22:38:14 +03:00
akritikos 664d676ab6 🔧 Updates overflow checking behavior for performance
Changes the default setting for CheckForOverflowUnderflow to false
to improve performance during math operations.
2026-08-26 22:38:13 +03:00
akritikos bc4c5de10c 🚨 Updates severity levels for C# compiler diagnostics and code quality analyzers in global configuration 2026-08-26 22:38:13 +03:00
akritikos f51e396bdb ✨ Adds OpenApi Source Generated Interceptors property group with namespaces 2026-08-26 22:38:13 +03:00
akritikos e4fe3d91c2 📝 Makes documentation optional for partial elements in samples & tests 2026-08-26 22:38:12 +03:00
akritikos 780f133885 📝 Makes documentation optional for samples & tests 2026-08-26 22:38:12 +03:00
akritikos 9a8dde4699 ✨ Adds 'main' as a source branch for feature mode in GitVersion configuration 2026-08-26 22:38:12 +03:00
akritikos 94a85e5ba4 ⬆️ Updates GitVersion.MsBuild to version 6.7.0 2026-08-26 22:38:12 +03:00
akritikos 6809901e8d ✨ Adds condition to PackageReference for Microsoft.AspNetCore.OpenApi 2026-08-26 22:38:11 +03:00
40 changed files with 1575 additions and 330 deletions

No files matched your search

+164 -1
View File
@@ -13,5 +13,168 @@ end_of_line = lf
[*.{xml,csproj,props,targets,nuspec}] [*.{xml,csproj,props,targets,nuspec}]
max_line_length = 1000 max_line_length = 1000
[{*.Generated.*.cs,**/Migrations/*.cs}] [*.{cs,vb}]
# Organize usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = true
csharp_using_directive_placement = inside_namespace:suggestion
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = file_scoped:warning
# this. preferences
dotnet_style_qualification_for_field = false:none
dotnet_style_qualification_for_property = false:none
dotnet_style_qualification_for_method = false:none
dotnet_style_qualification_for_event = false:none
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
# var preferences
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
csharp_style_expression_bodied_operators = when_on_single_line:suggestion
csharp_style_expression_bodied_properties = when_on_single_line:suggestion
csharp_style_expression_bodied_indexers = when_on_single_line:suggestion
csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
csharp_style_expression_bodied_lambdas = when_on_single_line:suggestion
csharp_style_expression_bodied_local_functions = when_on_single_line:suggestion
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:none
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
# Unused value preferences
csharp_style_unused_value_expression_statement_preference = discard_variable:none
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
# Index and Range preferences
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents_when_block = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_after_comma = true
csharp_space_before_comma = false
csharp_space_after_dot = false
csharp_space_before_dot = false
csharp_space_after_semicolon_in_for_statement = true
csharp_space_before_semicolon_in_for_statement = false
csharp_space_around_declaration_statements = false
csharp_space_before_open_square_brackets = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
# ReSharper/Rider custom properties (only honoured in .editorconfig, not .globalconfig)
# Inspection severities
resharper_class_never_instantiated_global_highlighting = none
resharper_class_never_instantiated_local_highlighting = none
resharper_convert_to_primary_constructor_highlighting = none
resharper_cognitive_complexity_threshold = 20
# Blank lines
resharper_blank_lines_around_region = 0
resharper_blank_lines_before_single_line_comment = 1
# Line breaks
resharper_new_line_before_while = true
resharper_place_accessor_attribute_on_same_line = never
resharper_place_accessorholder_attribute_on_same_line = never
resharper_place_field_attribute_on_same_line = never
resharper_wrap_before_binary_opsign = true
resharper_wrap_chained_method_calls = chop_if_long
resharper_wrap_linq_expressions = chop_always
resharper_wrap_ternary_expr_style = chop_always
# Spaces, alignment and usings
resharper_space_within_single_line_array_initializer_braces = true
resharper_alignment_tab_fill_style = use_spaces
resharper_qualified_using_at_nested_scope = true
# Naming (consolidated here from DotSettings + .globalconfig so Roslyn and Rider both enforce).
# Order matters: const and static-readonly fields are PascalCase and must be listed before
# the private-field camelCase rule so they are matched first (mirrors ReSharper's groups).
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = warning
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.symbols = static_readonly_fields
dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.static_readonly_fields.applicable_accessibilities = private
dotnet_naming_symbols.static_readonly_fields.required_modifiers = static,readonly
dotnet_naming_rule.private_fields_should_be_camel_case.severity = warning
dotnet_naming_rule.private_fields_should_be_camel_case.symbols = private_fields
dotnet_naming_rule.private_fields_should_be_camel_case.style = camel_case_style
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.camel_case_style.capitalization = camel_case
[*.vb]
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
[{*.Generated.*.cs,**/Migrations/*.cs,**/*ModelSnapshot.cs}]
generated_code = true generated_code = true
[{tests,samples}/**/*.cs]
dotnet_diagnostic.CS1591.severity = none
+3 -2
View File
@@ -1,2 +1,3 @@
Directory.Packages.props merge=union * text=auto
Directory.Packages.template.props merge=upstream-wins *.png binary
*.cs diff=csharp
@@ -0,0 +1,19 @@
Follow [gitmoji](https://gitmoji.dev) conventions. Use the **emoji character** (not the `:shortcode:`).
## Format
```
<emoji> <imperative summary, third person>
<longer explanation of what and why, wrap at 72 chars>
<issue references, e.g. Closes #123, Fixes PROJ-456>
```
- Subject line under 72 characters.
- Third-person imperative mood ("Adds feature", not "Add feature" or "Added feature").
- Do not end the subject with a period.
- Separate subject, body, and footer with blank lines.
- Body and footer are **optional** — only include when the subject alone isn't self-explanatory or when issues need linking.
- Body explains **what** changed and **why**.
- Footer links related issues (GitHub `Closes #N` / Jira `PROJ-N`).
+21
View File
@@ -0,0 +1,21 @@
# Project Guidelines
You are a senior software engineer and solution architect. Prioritize correctness, maintainability, and simplicity. Evaluate trade-offs before proposing solutions; prefer the least complex approach that meets requirements.
## Behaviour
- **Tone**: direct and concise — minimise prose, maximise actionable output.
- **Research first, act second** — always consult official documentation, codebase context, and project conventions **before** proposing or implementing changes. Never guess, assume API shapes, or rely on trial-and-error. If documentation is unclear or unavailable, say so and ask for guidance.
- When ambiguous or multiple approaches exist, **ask clarifying questions with 2–4 predefined options** (include trade-offs). Only proceed silently when intent is obvious.
- Briefly explain every suggestion: what it does, why, and how it fits the architecture.
- When goals conflict (e.g., performance vs readability), **favour performance** unless readability is significantly harmed.
- **Persist learnings** — when you discover a pattern, resolve a non-obvious issue, or make a decision worth remembering, save it to memory. Use repo memory for project-specific facts and user memory for general preferences. Keep memory up to date when instructions or project conventions change.
## Build & test
- Always build and test the entire solution (pass the solution slnx as a parameter to `dotnet build` and `dotnet test`).
## Documentation
- When a project has a `README.md`, treat it as part of the implementation: any rename or restructure that touches type names, configuration sections, or project references must update the affected `README.md` **in the same commit**.
- Before opening a PR, scan each touched project's existing `README.md` (if any) for stale references.
+12
View File
@@ -0,0 +1,12 @@
---
description: "Use when editing files under docs/adr/. Enforces ADR immutability and supersession rules."
applyTo: "docs/adr/**"
---
# ADR Editing Rules
ADRs are append-only history. To create a new ADR, use the `new-adr` skill.
- **Accepted ADRs are immutable.** Do not change `Context`, `Decision Drivers`, `Considered Options`, or `Decision Outcome` after acceptance — write a new ADR that supersedes instead.
- **Permitted edits to accepted ADRs**: typo/grammar fixes, adding links to related ADRs, and updating the `status` field as part of supersession or deprecation.
- **Superseding**: set the predecessor's frontmatter to `status: superseded by ADR-NNNN`, update its `date`, and add a back-link in its body. Never delete the predecessor.
- **Filenames are permanent.** Do not renumber or rename existing ADRs even if numbers have gaps.
@@ -0,0 +1,31 @@
---
description: "Use when editing analyzer or code-style configuration: .editorconfig, .globalconfig, stylecop.json, .DotSettings."
applyTo: ".editorconfig,.globalconfig,stylecop.json,*.DotSettings"
---
# Analyzer & Style Configuration
These files are the source of truth for code style and analyzer severity. Changes have wide blast radius.
> [!IMPORTANT]
> **Ask for explicit permission before editing.** State the rule(s), the new severity, and the rationale; wait for approval. Do not touch these files as part of unrelated work. The stated rationale belongs in the PR description.
## Guardrails
- **Do not relax a rule to silence a single occurrence.** Fix the code, or suppress narrowly with a justification comment in the offending file.
- New rules start at the **strictest justifiable severity**; downgrade later only with evidence.
- Never disable an entire analyzer category.
## File Roles
| File | Purpose |
| --- | --- |
| `.editorconfig` | Per-language formatting, naming rules, and analyzer severities scoped by file glob. |
| `.globalconfig` | Repo-wide analyzer severities not needing file-pattern scoping. |
| `stylecop.json` | StyleCop-specific settings (file headers, ordering, documentation). |
| `Solution.sln.DotSettings` | ReSharper/Rider mirror — **derived**, follows the others; do not lead changes here. |
## Coordination
- **A rule has one source of truth** across `.editorconfig`, `.globalconfig`, and `stylecop.json` — never duplicate.
- When a rule must appear in multiple files for IDE parity (e.g., mirrored to `Solution.sln.DotSettings`), severities **must match exactly**. Drift is a bug.
- StyleCop rules: configuration in `stylecop.json`, severity in `.editorconfig`.
@@ -0,0 +1,38 @@
---
description: "Use when writing API endpoints, routing, middleware, request/response handling, OpenAPI configuration, or HTTP pipeline setup in ASP.NET. Covers Minimal API conventions, error handling, and endpoint organisation."
---
# ASP.NET API Conventions
## Routing
- All endpoints live under `/api/v{apiVersion}/{resource}`.
- Default to `/api/v1` for projects without explicit API versioning.
## Endpoints
- Prefer **Minimal APIs**; use Controllers only when the endpoint group requires action filters, model binding customisation, or exceeds 10 endpoints sharing significant cross-cutting logic.
- Group related endpoints using `MapGroup()` with a shared prefix and tag.
- Use **typed results** (`TypedResults.Ok()`, `TypedResults.NotFound()`) over untyped `Results` for OpenAPI metadata inference.
- Return **`ProblemDetails`** (RFC 9457) for all error responses — configure via `AddProblemDetails()`.
## Authorisation
- Apply `.RequireAuthorization()` at the group level for protected resources.
- Reference policy names through `const string` fields on a shared static class (e.g., `.RequireAuthorization(AuthorizationPolicies.RequireAdminRole)`) instead of inline string literals.
- Mark public endpoints explicitly with `.AllowAnonymous()`.
## Request Handling
- Bind request data with **`[AsParameters]`** for complex parameter sets.
- Validate input at the endpoint boundary — use **filters** or **`IValidatableObject`** to fail fast.
- Use **`CancellationToken`** on all async endpoints.
## Endpoint Organisation
- One file per resource or feature area (e.g., `UserEndpoints.cs`, `OrderEndpoints.cs`).
- Register via extension methods on `IEndpointRouteBuilder`: `MapUserEndpoints()`.
- Keep endpoint lambdas thin — delegate business logic to injected services.
## OpenAPI
- Annotate endpoints with `.WithTags()` for grouping in the generated spec.
@@ -0,0 +1,29 @@
---
description: "Use when writing or modifying C# source code. Covers non-obvious defaults not caught by analyzers."
applyTo: "**/*.cs"
---
# C# Conventions
Code style is enforced by `.editorconfig`, `.globalconfig`, and StyleCop analyzers — do not restate their rules.
## Non-Obvious Defaults
- XML doc comments required on all `public` and `protected` members in `src/` (suppressed in `tests/` and `samples/`).
- Avoid `null!` (null-forgiving operator) — fix the nullability flow instead of suppressing the warning.
## Comments
Applies to `src/`. Tests keep the guidance in the testing instructions.
- **No comments inside member bodies.** Anything worth saying goes in an XML doc comment on the member that says it.
- Document `private` and `internal` members — the analyzers only *require* docs on exposed elements, they do not object to more. Put the "why" in `<remarks>`.
- If the explanation is about one statement rather than the whole member, extract that statement into a named private method and document that instead.
- For logic inside lambdas or local functions where an XML doc comment is not applicable, extract the logic into a named private method and document that method instead.
- Never state what the code already shows, and never narrate history — a past bug, a change, or an answer to a reviewer belongs in the commit message, where it cannot go stale.
- Sole exception: the justification required beside a narrow analyzer suppression, which has nowhere else to live.
## Patterns
- Prefer **records** for DTOs, value objects, and other immutable data carriers.
- Use `LoggerMessage`-generated `partial` methods on a `partial class` — never log inline (e.g., `logger.LogInformation(…)`). Do not make existing types partial without explicit user sign-off. Do not fall back to inline logging.
- If a type cannot be made partial (no user sign-off obtained), do not modify its logging calls — surface the conflict to the user and wait for instruction rather than silently falling back to inline logging. Present at least these options: (1) make the type `partial`; (2) move the `LoggerMessage` methods to a separate type — group reusable messages in one shared class, and keep the rest in a per-type class.
@@ -0,0 +1,31 @@
---
description: "Use when editing Dockerfile, compose files, or Docker-related configuration. Covers guardrails for the multi-stage build and runtime image selection."
applyTo: "docker/**,compose*.yaml"
---
# Docker Conventions
`docker/Dockerfile` is a multi-stage pipeline — stage names and purposes are visible in the file itself.
## Guardrails
- **Build context** is always the repo root, not `docker/`.
- **`COPY --link`** is used intentionally for layer cache — do not replace with plain `COPY`.
- **Cache mounts** (`--mount=type=cache,target=/root/.nuget/packages`) must stay on restore, build, test, and publish steps.
- **Stage dependency chain** must be preserved (e.g., `build` → `restore`, `test` → `build`, `publish` → `test`).
- New stages should follow the existing pattern: `FROM <parent> AS <name>`.
## Build Args
- `RUNTIME_BASE`: `web` (ASP.NET), `app` (console), or `self-contained`. If a use case does not match `web`, `app`, or `self-contained`, do not invent a new `RUNTIME_BASE` value — flag this to the user and ask which existing value best fits their scenario.
- `CONFIGURATION`: `Release` (default) or `Debug`
- `PUBLISHED_PROJECT`: Project name to publish (without path or extension)
- `DATABASE_PROJECT`: EF Core project for migration bundles
- `DBCONTEXT`: Optional DbContext name for migrations. If omitted, the migration bundle step must not pass `--context`; EF Core auto-discovers the single DbContext in `DATABASE_PROJECT`.
## Image Selection
| Use Case | `RUNTIME_BASE` | Base Image |
|----------|----------------|------------|
| ASP.NET web apps | `web` | `aspnet:*-alpine-composite-extra` |
| Console / worker | `app` | `runtime:*-alpine-extra` |
| Self-contained | `self-contained` | `runtime-deps:*-alpine-extra` |
@@ -0,0 +1,47 @@
---
description: "README.md authoring: structure, callouts, diagrams, and assets."
applyTo: "**/README.md"
---
# README Style
## Structure
Follow this ordering when sections apply; omit those that don't:
1. **Title** (`# <ProjectName>`) and one-sentence purpose.
1. **Getting Started** — minimal commands to consume or run the project.
1. **Features** / **Capabilities** — bulleted highlights.
1. **Configuration** — build args, environment variables, MSBuild properties.
1. **Usage Examples** — code or CLI snippets.
1. **Recommendations** / **Caveats** — known limitations, in callouts.
1. **Reference link definitions** at the bottom.
## Conventions
- Do not hard-wrap prose; one paragraph per line.
- Ordered lists: write every item as `1.` and let the renderer auto-number.
- Use reference-style links for external URLs in prose, with definitions at the bottom of the file. Inline links are fine in tables and for in-repo relative paths.
- Keep code examples minimal — strip boilerplate unless it is the point.
## Callouts
Use [GitHub-flavoured alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) for emphasis; reserve plain `>` blockquotes for quoted text.
| Alert | Use for |
| --- | --- |
| `> [!NOTE]` | Neutral context the reader should know |
| `> [!TIP]` | Optional best-practice |
| `> [!IMPORTANT]` | Required for correct usage |
| `> [!WARNING]` | Risk of breakage or data loss |
| `> [!CAUTION]` | Security or destructive-action risk |
## Mermaid Diagrams
- Match diagram type to intent: `flowchart` (processes), `sequenceDiagram` (interactions over time), `classDiagram` (type relationships), `erDiagram` (data models).
- Keep diagrams under ~15 nodes; split larger ones.
- No custom styling — defaults render in both light and dark modes.
## Assets
- Repo-wide assets in `/docs/assets/`; project-scoped assets in the project's own `docs/assets/`.
- Prefer **SVG** for diagrams and logos; PNG only for raster screenshots.
@@ -0,0 +1,45 @@
---
description: "Use when editing MSBuild files (.csproj, .props, .targets). Covers central package management, artifacts layout, and property inheritance."
applyTo: "**/*.{csproj,props,targets}"
---
# MSBuild Conventions
## Central Package Management
All package versions are declared in `Directory.Packages.props` at the repo root. In `Directory.Packages.props`, ensure the last child element of the root `<Project>` tag is `<Import Project="Directory.Packages.template.props" />`. `Directory.Packages.template.props` is **READ ONLY**, never edit it. The template provides default `<PackageVersion>` entries; any entry with the same `Include` declared earlier in `Directory.Packages.props` takes precedence over the template default, because MSBuild uses first-definition-wins semantics and the import appears last.
In `.csproj` files:
```xml
<!-- Correct -->
<PackageReference Include="Newtonsoft.Json" />
<!-- Wrong — never specify Version -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
```
To add or update a version, edit `Directory.Packages.props`:
```xml
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
```
If the package does not exist in the template, simply add a new `<PackageVersion>` entry in `Directory.Packages.props`. No override logic is needed; the entry will be the sole definition.
## Properties Set Centrally (Do Not Override)
These are configured in the root `Directory.Build.props` — do **not** set them in individual projects:
`LangVersion`, `Nullable`, `ImplicitUsings`.
## InternalsVisibleTo
Handled automatically via `<InternalsVisibleToSuffix>` in the root props. Default suffixes are `.Tests` and `Tests`. To add custom visibility:
```xml
<ItemGroup>
<InternalsVisibleTo Include="MyProject.IntegrationTests" />
</ItemGroup>
```
This is in addition to the automatically generated entries; do not remove or duplicate the default suffix entries.
@@ -0,0 +1,26 @@
---
description: "Use when adding tracing, metrics, or feature flags: ActivitySource/Meter setup, semantic-convention tags, OTLP exporter config, OpenFeature client usage and flag-key naming."
---
# Observability & Feature Flags
## OpenTelemetry
- One **`ActivitySource`** per logical component, named `Kritikos.<Project>.<Component>`. Declare as `static readonly` on a dedicated `Telemetry` static class within the component (avoid scattering sources across every type).
- One **`Meter`** per component, alongside its `ActivitySource`. The names **may** match when both belong to the same component.
- Always wrap `StartActivity(...)` in a `using` — leaked activities skew downstream timings.
- **Activity names**:
- When [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) cover the operation (HTTP, DB, messaging, RPC), follow semconv exactly (`HTTP GET`, `db.query`, `messaging.process`).
- For custom operations not covered by semconv: `<Verb><Object>` in PascalCase (`ProcessOrder`, `LoadConfiguration`). Avoid generic verbs like `Handle` or `Execute`.
- **Tags / attributes**: lowercase dotted, follow semantic conventions where they exist (`http.request.method`, `db.system`, `messaging.destination.name`). Project-specific tags use the `kritikos.<area>.<name>` namespace.
- **Metric instruments**: snake_case names with units in the suffix (`orders_processed_total`, `request_duration_seconds`). Always set `unit` and `description` at creation.
- **Resource attributes**: when a shared registration helper is added, it should populate `service.name` from `AssemblyName` and `service.version` from the GitVersion-computed `InformationalVersion`. Do not set them manually at call sites.
- **Exporter**: OTLP over gRPC, endpoint via `OTEL_EXPORTER_OTLP_ENDPOINT`. Do not register console exporters in `Release` builds.
- **Sampling**: parent-based with `TraceIdRatioBased` (1.0 in dev, configurable in prod). Do not set custom samplers without justification.
## OpenFeature
- Resolve flags through the configured OpenFeature client (obtained via DI, or `Api.Instance.GetClient()` if no DI integration is wired). Never call provider SDKs directly.
- **Flag keys**: `kebab-case`, prefixed by domain (`orders-allow-partial-fulfilment`, `auth-require-mfa`). Keys are stable contracts — treat renames like API breaking changes.
- Always pass `defaultValue:` — `client.GetBooleanValue("flag", defaultValue: false, context)`.
- **Evaluation context** is built once per request via the configured context provider — do not assemble ad-hoc contexts inline.
- Long-lived flags (kill switches, licensing) live in code; short-lived flags (rollouts, experiments) must have a removal date in their description and a tracking issue.
@@ -0,0 +1,28 @@
---
description: "Use when adding, removing, or moving projects, or when editing the solution file or VS Code workspace."
applyTo: "*.slnx,*.sln,Solution.code-workspace"
---
# Solution Conventions
`Solution.slnx` (XML) is the canonical solution format. The legacy `.sln` is not used; do not regenerate it.
## Adding & Removing Entries
Any project, configuration, or asset file added to, removed from, or renamed in a tracked location **must** be reflected in `Solution.slnx` in the same commit. New top-level folders also require an entry in `Solution.code-workspace`.
Place entries in the virtual folder matching the on-disk location:
| On-disk location | Virtual folder |
| --- | --- |
| `src/**`, `samples/**`, `tests/**` (projects + their `Directory.Build.props`) | `/src/`, `/samples/`, `/tests/` |
| Repo-root config files (`.editorconfig`, `Directory.*.props`, `GitVersion.yml`, etc.) | `/Configuration/` |
| Repo-root assets (`README.md`, `LICENSE.md`, `icon.png`, logos) | `/Assets/` |
Reserved virtual folder names must not be renamed.
## Renames
- Update the `.slnx` entry, the on-disk path, and any `ProjectReference` paths in dependent projects in the same commit.
- Never leave dangling `<File Path="…" />` or project entries.
After any `.slnx` change, run `dotnet build` to confirm all referenced projects load.
@@ -0,0 +1,24 @@
---
description: "Use when creating or modifying test projects under the tests/ folder. Covers naming conventions and structural guardrails."
applyTo: "tests/**"
---
# Test Project Conventions
Build configuration is handled by `tests/Directory.Build.props` — do not restate its settings.
## Framework
- **Testing**: TUnit.
- **Mocking**: NSubstitute (analyzers auto-added when referenced).
## Naming
- Test project: `<ProjectUnderTest>.Tests` (matches InternalsVisibleTo default).
- Test classes: `<ClassUnderTest>Tests`.
- Test methods: must use `MethodName_Condition_ExpectedResult` format. Example: `Add_NegativeNumbers_ThrowsArgumentException`.
## Structure
- Follow **Arrange / Act / Assert**.
- Always propose a set of basic tests for new or changed code. A basic test set must include at minimum: one happy-path test, one test per documented edge case or boundary condition, and one test for each expected exception.
- If no edge cases are explicitly documented, use judgment to identify and cover the most likely boundary conditions (e.g. null inputs, empty collections, zero/max values) and note the assumption in a comment.
@@ -0,0 +1,51 @@
---
description: "Audit .github/instructions/ and .github/skills/ for duplication, stale references, and unscoped or misscoped files."
agent: "agent"
---
# Audit Instructions & Skills
Walk every file under `.github/instructions/` and `.github/skills/` and produce a prioritised report of issues. Make no edits unless the user approves them after reading the report.
## Steps
### 1. Inventory
List every `*.instructions.md` and every `**/SKILL.md`, plus `copilot-instructions.md` and any `*.prompt.md`.
### 2. Per-File Checks
For each instructions file:
- `applyTo` glob exists and matches actual files in the repo (no dead globs).
- `description` accurately reflects the content (no stale TOCs, no over-promises).
- Content is project-specific — flag anything restating universal Markdown / C# / formatter rules, or duplicating the agent runtime (e.g., "work in parallel", "save to memory").
- File defers to enforcement layers (`.editorconfig`, analyzers, `Directory.Build.props`) instead of restating their rules.
- Cross-references point at files that exist.
For each skill:
- Frontmatter `name` matches the directory name.
- `description` starts with the action and includes "Use when:".
- Procedure steps are actionable, not narration.
- Commands actually work against this repo's tool versions and config files.
- Cross-skill references use relative paths.
### 3. Cross-File Checks
- Same rule defined in multiple files with different wording or severity → flag.
- Topics not covered by any file but enforced via PR comments / convention → flag as candidate new file.
- `applyTo` overlap that could cause conflicting guidance on a single file → flag.
### 4. Report
Produce a table sorted by priority (high / medium / low):
| Priority | File | Issue | Suggested fix |
End with two summary counts: total files inspected, total issues found.
## Guardrails
- Read-only by default. Apply fixes only if the user explicitly approves them.
- When suggesting a fix, quote the exact lines to change so the user can decide without re-reading the file.
@@ -0,0 +1,65 @@
---
description: "Convert an MVC controller to Minimal API endpoints following the project's ASP.NET conventions."
agent: "agent"
---
# Convert Controller to Minimal API
Refactor an MVC controller into Minimal API endpoints aligned with [aspnet-api.instructions.md](../instructions/aspnet-api.instructions.md).
## Input
Path to the controller file (e.g., `src/MyApi/Controllers/OrdersController.cs`). Ask if not provided.
## Steps
### 1. Analyse the Controller
For each action method, capture:
- HTTP verb and route template.
- Parameter binding sources (`[FromRoute]`, `[FromQuery]`, `[FromBody]`, `[FromServices]`).
- Return type and possible status codes.
- Filters / attributes (`[Authorize]`, `[ProducesResponseType]`, etc.).
- Async signature and `CancellationToken` usage.
### 2. Produce a Migration Plan
Present a table to the user before writing any code:
| Action | New endpoint | Notes (auth, filters, response types) |
Ask for confirmation or adjustments.
### 3. Generate the Endpoint File
Create `<Resource>Endpoints.cs` next to the controller, following the conventions:
- Static class with a `MapXEndpoints(this IEndpointRouteBuilder)` extension.
- `MapGroup("/api/v{apiVersion}/{resource}")` with shared `.WithTags(...)`.
- Use **`TypedResults`** for every return path.
- Use **`[AsParameters]`** for complex parameter sets.
- Use **`CancellationToken`** on every async lambda.
- Errors return **`ProblemDetails`** via `TypedResults.Problem(...)`.
- Endpoint lambdas stay thin; delegate to injected services.
### 4. Wire Up Registration
In `Program.cs`, replace `MapControllers()` (or supplement it) with the new `MapXEndpoints()` call. If the controller was the last one, also remove `AddControllers()`.
### 5. Migrate Tests
For each test targeting the controller, port it to use `WebApplicationFactory` against the new endpoint. Keep the file name and test names; update the arrange/act sections only.
### 6. Delete the Controller
Only after the new endpoints + tests pass. Run `dotnet build` and `dotnet test` before deletion.
### 7. Update README
If the project's `README.md` documented the old controller routes, update it in the same commit (per [copilot-instructions.md](../copilot-instructions.md)).
## Guardrails
- Do not change behaviour while converting — refactor first, behaviour changes go in a separate commit.
- If a controller uses filters or model binders without a Minimal API equivalent, surface the gap and ask before inventing one.
@@ -0,0 +1,66 @@
---
description: "Convert inline logger calls to LoggerMessage-generated partial methods, per the C# conventions."
agent: "agent"
---
# Refactor to LoggerMessage
Replace inline `logger.LogX(...)` calls with `LoggerMessage`-generated `partial` methods, as required by [csharp.instructions.md](../instructions/csharp.instructions.md).
## Input
A file or project path. If unspecified, default to the active editor file.
## Steps
### 1. Inventory
Find every `ILogger.Log*(...)` call site (`LogTrace`, `LogDebug`, `LogInformation`, `LogWarning`, `LogError`, `LogCritical`). Group by containing class.
### 2. Plan
For each class with hits, present a table before editing:
| Method | Level | EventId | Message template | Args |
Pick stable, sequential `EventId` values per class (start at 1 within the class). Confirm with the user when message templates need to be reworded for clarity.
### 3. Convert the Class
- Mark the class `partial`.
- Add a nested `static partial class Log` (or top-level partial methods, per existing project style — match what's already in the codebase).
- For each call site, generate:
```csharp
[LoggerMessage(EventId = N, Level = LogLevel.X, Message = "...")]
static partial void <Verb><Subject>(ILogger logger, <args>);
```
- Replace each call site with the new method invocation.
- Method names: `PascalCase`, verb-led, third-person (`OrderProcessed`, not `LogOrderProcessed` or `OrderWasProcessed`).
### 4. Handle Edge Cases
- **Exceptions**: `Exception` parameter goes first; do not include it in the message template.
- **Scopes** (`logger.BeginScope`): leave alone — `LoggerMessage` does not replace scopes.
- **Conditional logging** (`if (logger.IsEnabled(...))`): drop the guard; the generated method already checks.
### 5. Verify
```bash
dotnet build
```
Source generators must produce zero warnings. If a `[LoggerMessage]` definition is rejected, surface the analyzer message and the offending method.
### 6. Run Tests
```bash
dotnet test
```
Logger-based assertions in tests usually keep working, but message-template changes can break string-matching tests — flag any test failures explicitly.
## Guardrails
- Do not change log levels while refactoring — that's a separate decision.
- Do not invent new log statements; only convert what already exists.
- If a class is `sealed` and has external partial declarations, surface the conflict before adding `partial` to the type.
@@ -0,0 +1,62 @@
---
description: "Create a temporary markdown file summarising all branch changes vs. main/master for PR review"
agent: "agent"
---
# Summarize Branch Changes for PR
Create a temporary markdown file in the repository root called `BRANCH_CHANGES.md` that summarises all changes on the current branch compared to the master/main/default branch. This file is intended to aid PR review and should be deleted before merging.
## Input
No explicit input required — the summary is derived from git history and the current Copilot session context.
## Steps
### 1. Gather Git Context
- Determine the current branch name (`git branch --show-current`).
- Find the merge base with `origin/master`.
- Collect the commit log between the merge base and HEAD (`git log --oneline`).
- Collect the diff stat (`git diff --stat`), file change list (`--diff-filter`), and numstat.
### 2. Distil Session Requests (if applicable)
If Copilot session context is available, extract the key user requests that drove the changes and present them as a bullet-point list at the top of the file under a **Copilot Session Requests** heading.
### 3. Produce the Markdown File
Create `BRANCH_CHANGES.md` in the repository root with the following sections:
#### Header
- Branch name, base branch, and current date.
#### Copilot Session Requests
- Bullet list of the user prompts/requests from the current session that led to changes (omit if no session context).
#### Commits
- Table with columns: Hash, Message, Author, Date.
#### Files Changed
- Table with columns: File, Change type (Added/Modified/Deleted), Insertions, Deletions.
- Summary line: _N files changed, X insertions, Y deletions._
#### Change Details
- One sub-heading per changed file (or logical group of related files).
- Numbered list of the distinct changes made, written for a reviewer who is unfamiliar with the recent context.
#### Pending Session Work (if applicable)
- Any in-progress or uncommitted work from the current Copilot session that has not yet been committed.
## Guidelines
- Keep descriptions concise but specific — a reviewer should understand _what_ changed and _why_ without reading the diff.
- Use git data as the source of truth; supplement with session context only for intent and motivation.
- Do not include the full diff content — summarise it.
- Mark the file clearly as temporary (mention it should be deleted before merge).
@@ -0,0 +1,72 @@
---
description: "Sync the current repository with upstream changes from kritikos-io/templates-dotnet, with conflict-resolution guidance."
agent: "agent"
---
# Sync From Template
Pull updates from the upstream `kritikos-io/templates-dotnet` repository, following the workflow documented in the root `README.md`.
## Steps
### 1. Verify the `template` Remote
```bash
git remote -v | grep template
```
If absent, add it and warn the user that the first sync requires `--allow-unrelated-histories`:
```bash
git remote add template https://github.com/kritikos-io/templates-dotnet
git fetch --all
```
### 2. Check Working Tree
`git status` must be clean. If it isn't, stop and ask the user to commit or stash before continuing.
### 3. Pull
- **First-time sync** (template remote was just added):
```bash
git merge template/main --allow-unrelated-histories
```
- **Subsequent syncs**:
```bash
git pull template main
```
### 4. Resolve Conflicts
Common conflict zones, with resolution guidance:
| File / area | Strategy |
| --- | --- |
| `Solution.slnx`, `Solution.code-workspace` | Keep local — these are project-specific. Re-apply any new entries from upstream manually. |
| `Directory.Build.props`, `Directory.Build.targets`, `Directory.Packages.props` | Take upstream as the base, re-apply project-specific overrides on top. |
| `.github/instructions/`, `.github/skills/`, `.github/prompts/` | Take upstream; project-specific guidance should live in a *separate* file, never as edits to template-shipped files. |
| `README.md`, `LICENSE.md`, `icon.png` | Keep local — these are project-specific. |
| `docker/Dockerfile` | Take upstream; project-specific compose lives in `docker/compose.*.yaml`. |
When a conflict needs human judgement, list it with file path + decision options rather than guessing.
### 5. Verify
```bash
dotnet restore --force-evaluate
dotnet build
dotnet test
```
If lock files moved, commit `packages.lock.json` updates.
### 6. Commit
Use a single merge commit; do not squash. Subject:
```
🔀 Syncs with kritikos-io/templates-dotnet
```
(Per [copilot-commit-message-instructions.md](../copilot-commit-message-instructions.md): gitmoji, third-person imperative.)
+86
View File
@@ -0,0 +1,86 @@
---
name: docker-build
description: "Build, test, publish, or pack .NET projects using the multi-stage Docker pipeline. Use when: building Docker images, running containerized tests, creating migration bundles, publishing to containers, or troubleshooting Dockerfile stages."
argument-hint: "Describe what you want to build or publish (e.g., 'publish WebApplication1 as web app')"
---
# Docker Build Skill
## When to Use
- Build and run a .NET project in Docker
- Run tests inside a container
- Create a NuGet package via Docker
- Create an EF Core migration bundle
- Troubleshoot multi-stage Docker build issues
## Prerequisites
- Docker Desktop or Docker Engine running
- Repository root as build context
## Common Workflows
### Build and run a web application
```shell
docker compose -f docker/compose.sample.yaml build sample-api \
--build-arg PUBLISHED_PROJECT=<ProjectName>
docker compose -f docker/compose.sample.yaml up sample-api
```
### Build self-contained application
```shell
docker build -f docker/Dockerfile \
--target final \
--build-arg RUNTIME_BASE=self-contained \
--build-arg PUBLISHED_PROJECT=<ProjectName> \
-t myapp .
```
### Run tests in container
```shell
docker build -f docker/Dockerfile --target test .
```
### Lint OpenAPI documents
```shell
docker build -f docker/Dockerfile --target openapi-lint .
```
### Pack NuGet packages
```shell
docker build -f docker/Dockerfile --target pack --output artifacts/nuget .
```
### Create EF Core migration bundle
```shell
docker build -f docker/Dockerfile --target migrations \
--build-arg PUBLISHED_PROJECT=<StartupProject> \
--build-arg DATABASE_PROJECT=<EFProject> \
--build-arg DBCONTEXT=<OptionalContextName> \
-t migrations .
```
## Stage Reference
See [Dockerfile](../../docker/Dockerfile) for the full multi-stage pipeline. Key stages and their targets:
| `--target` | Produces |
|------------|----------|
| `test` | Runs `dotnet test` — exits non-zero on failure |
| `openapi-lint` | Spectral lint on generated OpenAPI JSON |
| `publish` | Published app in `/app/publish` |
| `pack` | NuGet `.nupkg` files in `/app/publish` |
| `migration-bundle` | Standalone EF migration binary |
| `final` | Production runtime image |
## Troubleshooting
- **Restore failures**: Check `nuget.config` package sources and ensure `packages.lock.json` files are committed.
- **GitVersion errors**: The `gitversion` stage needs `.git/` — ensure the build context includes it.
- **Missing OpenAPI docs**: The `openapi-lint` stage only runs Spectral if `*.json` files exist in `artifacts/OpenApi/`.
+56
View File
@@ -0,0 +1,56 @@
---
name: ef-migration
description: 'Add, remove, or apply Entity Framework Core migrations against a project under src/. Use when: creating a new migration, reverting the last migration, generating a migration bundle, applying migrations to a database.'
argument-hint: 'Describe the schema change (e.g., "add audit columns to Orders") and the target DbContext if multiple exist'
---
# EF Core Migration
## Prerequisites
- The EF project (containing the `DbContext`) is referenced by — or is itself — a runnable startup project.
- Requires `dotnet ef`: `dotnet tool restore` (if a manifest exists) or `dotnet tool install -g dotnet-ef`.
## Conventions
- **Migration name**: `PascalCase`, imperative, third person, ≤ 60 chars (e.g., `AddsOrderAuditColumns`, not `audit_changes` or `Migration1`).
- **Output folder**: default `Migrations/` inside the EF project. Do not relocate.
- **One DbContext per command** — pass `--context` whenever the project has more than one.
- **Never edit a migration after it has been applied to a shared environment.** Add a corrective migration instead.
- **Commit migrations together with the model change** that produced them.
## Procedure
The **EF project** contains the `DbContext`; the **startup project** is the runnable project EF executes against (usually a web/worker referencing the EF project).
1. **Add the migration:**
```bash
dotnet ef migrations add <PascalCaseName> \
--project src/<EFProject> \
--startup-project src/<StartupProject> \
--context <DbContextName>
```
2. **Inspect** the generated `*.cs` and `*.Designer.cs` files for unintended changes (unrelated columns, dropped indices).
3. **If wrong, remove before committing:**
```bash
dotnet ef migrations remove --project src/<EFProject> --startup-project src/<StartupProject>
```
For a deployable migration binary, use the [docker-build](../docker-build/SKILL.md) skill's `migrations` target.
## Generating an SQL Script
```bash
dotnet ef migrations script <FromMigration> <ToMigration> \
--project src/<EFProject> \
--startup-project src/<StartupProject> \
--idempotent \
--output artifacts/migrations.sql
```
Use `--idempotent` whenever the script may run against a database in an unknown state.
## Troubleshooting
- **"Unable to create a 'DbContext'…"** — pass `--startup-project` explicitly; auto-detection picks the wrong project in multi-project solutions.
- **Multiple DbContexts found** — pass `--context <Name>`.
+70
View File
@@ -0,0 +1,70 @@
---
status: proposed
date: YYYY-MM-DD
decision-makers: [names or roles]
# consulted: [subject-matter experts with two-way communication]
# informed: [stakeholders kept up-to-date with one-way communication]
---
# NNNN. {short title, representative of solved problem and found solution}
## Context and Problem Statement
{Describe the context and problem statement in two to three sentences, or as a short illustrative story. Articulate the problem as a question if helpful, and link to issues, PRs, or discussions.}
## Decision Drivers
- {decision driver 1, e.g., a force, facing concern, quality attribute}
- {decision driver 2}
- …
## Considered Options
- {title of option 1}
- {title of option 2}
- {title of option 3}
- …
## Decision Outcome
Chosen option: **"{title of option X}"**, because {justification — e.g., the only option meeting a k.o. criterion, resolves driver {driver}, or comes out best in the comparison below}.
### Consequences
- Good, because {positive consequence}.
- Bad, because {negative consequence / accepted trade-off}.
- Follow-up: {action item, if any}.
<!-- Optional. Remove if not used. -->
### Confirmation
{How will compliance with this ADR be confirmed? E.g., a design/code review, an ArchUnit test, a CI check, or a follow-up audit.}
<!-- Optional. Remove if not used. -->
## Pros and Cons of the Options
### Comparison
| Driver | {Option 1} | {Option 2} | {Option 3} |
| ---------- | ---------- | ---------- | ---------- |
| {driver 1} | Yes | Maybe | No |
| {driver 2} | No | Yes | Yes |
### {title of option 1}
{example | description | pointer to more information}
- Good, because {argument}.
- Neutral, because {argument}.
- Bad, because {argument}.
### {title of option 2}
{example | description | pointer to more information}
- Good, because {argument}.
- Bad, because {argument}.
<!-- Optional. Remove if not used. -->
## More Information
{Additional evidence/confidence for the decision, team agreement notes, when/how to revisit, links to related ADRs and resources.}
+97
View File
@@ -0,0 +1,97 @@
---
name: new-adr
description: 'Create a new Architectural Decision Record (ADR) capturing a justified design choice that addresses an architecturally significant functional or non-functional requirement. Use when: creating a new ADR, documenting an architectural choice, recording a design decision, superseding a previous decision, capturing rationale for a framework/library/pattern selection.'
argument-hint: 'Brief description of the decision (e.g., "adopt Minimal APIs over MVC controllers")'
---
# New Architectural Decision Record
You are assisting the user in producing a well-structured, comprehensive ADR. Ask clarifying questions, offer suggestions and examples, and ensure the record follows the standard format with all required sections filled.
Reference: <https://adr.github.io>.
## When to Use
- A design choice has a **measurable effect on architecture or quality attributes** (security, performance, scalability, maintainability, cost, DX).
- The decision is **non-obvious**, has **trade-offs**, or **supersedes** prior guidance.
- A reviewer or future maintainer would reasonably ask *"why did we do it this way?"*.
**Not an ADR**: cosmetic refactors, bug fixes, style preferences, or decisions with no viable alternatives. Use a commit message or code comment instead.
## Location & Filename
- **Folder**: `docs/adr/`
- **Filename**: `NNNN-kebab-title.md` (zero-padded, four digits, sequential; e.g., `0001-use-minimal-apis.md`).
- **Index** (optional): `docs/adr/README.md` listing all ADRs with status.
Determine the next `NNNN` by scanning existing files and incrementing the highest number. Never reuse numbers, even for retracted ADRs.
## Required Sections
Every ADR must include these MADR sections, in order:
1. **Context and Problem Statement** — the situation, goals, and constraints that frame the decision; pose the problem as a question when helpful.
2. **Decision Drivers** — bullet list of forces, concerns, and quality attributes that matter.
3. **Considered Options** — bullet list of viable alternatives.
4. **Decision Outcome** — the chosen option, justification, nested **Consequences** (good/bad/follow-up), and optional **Confirmation** subsection.
MADR-optional sections (include when they add value):
- **Pros and Cons of the Options** — per-option Good/Neutral/Bad bullets. Prefix with the comparison table below when more than two options compete.
- **More Information** — links, revisit notes, related ADRs.
### Comparison Table (project addition)
When using **Pros and Cons of the Options**, lead with a Yes/No/Maybe matrix scoring each option against each driver. This is a project convention on top of MADR, not part of the spec, but it forces explicit comparison and exposes weak options.
```markdown
| Driver | Option A | Option B | Option C |
| ---------- | -------- | -------- | -------- |
| {driver 1} | Yes | Maybe | No |
| {driver 2} | No | Yes | Yes |
```
## Status Lifecycle
`proposed` → `accepted` → (`deprecated` | `superseded by ADR-NNNN`) · `rejected` is terminal from `proposed`.
- New ADRs start as `proposed` unless the user confirms acceptance.
- When superseding, **update the old ADR's status** to `superseded by ADR-NNNN` and add a back-link. Never rewrite history of an accepted ADR.
- `date` reflects the last status change.
## MADR Template
This skill follows the [MADR 4.0](https://adr.github.io/madr/) (Markdown Any Decision Records) format with one project addition (see *Comparison Table* above). Copy [MADR.md](MADR.md) to `docs/adr/NNNN-kebab-title.md` and fill in the placeholders. The folder `docs/adr/` is a project convention; MADR's own recommendation is `docs/decisions/`.
## Procedure
1. **Confirm significance.** Check against the "When to Use" criteria. If it doesn't qualify, suggest a lighter alternative (code comment, PR description, CHANGELOG entry) and stop.
2. **Assign a number.** List `docs/adr/` and pick the next `NNNN`.
3. **Interview the user — one section at a time.** Ask focused questions for the current section, offer suggestions/examples where useful, then move on. Do not dump every question at once.
4. **Show progress** after each section using a status table with these markers:
- ✔️ completed
- 🟡 in progress
- ➖ not started
```markdown
| Section | Status |
| ----------------------------- | ------ |
| Context and Problem Statement | ✔️ |
| Decision Drivers | 🟡 |
| Considered Options | ➖ |
| Decision Outcome | ➖ |
| Consequences | ➖ |
| Pros and Cons (optional) | ➖ |
```
5. **Draft the ADR** as sections are filled. Keep the title short and decision-oriented (`"Use X for Y"` or `"Adopt X over Y"`). Status = `proposed` unless the user confirms acceptance.
6. **Handle supersession.** If this ADR replaces another, update the predecessor's frontmatter `status` to `superseded by ADR-NNNN` and add a cross-link in its body.
7. **Update index.** If `docs/adr/README.md` exists, append the new entry with status; otherwise offer to create one.
8. **Save & confirm.** Write the file to `docs/adr/NNNN-kebab-title.md`, validate frontmatter YAML and filename, and confirm the saved path back to the user.
## Quality Bar
- **Title states the decision**, not the topic. ✅ `Use Minimal APIs for new endpoints` · ❌ `API style`.
- **Options are real alternatives** that were genuinely considered — not strawmen.
- **Consequences include the downsides** we accept. An ADR with only positives is incomplete.
- **Links > prose** for context already documented elsewhere (issues, RFCs, benchmarks).
- **Immutable once accepted.** Further changes happen via a new ADR that supersedes.
+48
View File
@@ -0,0 +1,48 @@
---
name: new-library
description: 'Scaffold a new reusable .NET library with correct naming, multi-targeting, and structure. Use when: creating a new library project, adding a reusable package, setting up a shared library under src/.'
argument-hint: 'Brief description of the library purpose (e.g., "hashing utilities", "EF Core auditing")'
---
# New Library
## When to Use
- Creating a new reusable, packable library under `src/`
- Adding a shared component meant for NuGet distribution
## Naming Convention
Libraries use a `{Domain}.{Feature}` pattern. The `Kritikos.` root namespace prefix is applied automatically by `Directory.Build.props`.
| Domain prefix | When to use | Example |
|---|---|---|
| `AspNetCore.{Feature}` | Depends on `Microsoft.AspNetCore.App` | `AspNetCore.ProblemDetails` |
| `Extensions.{Feature}` | Framework-agnostic, depends only on `Microsoft.Extensions.*` | `Extensions.Hashing` |
| `EntityFrameworkCore.{Feature}` | Depends on EF Core | `EntityFrameworkCore.Auditing` |
| *(no prefix)* | Pure .NET with no framework dependency | `Primitives` |
**Always propose 2–4 name options** to the user and allow a custom choice.
## Multi-Targeting
Target **both current LTS versions** plus optionally **one STS version** if newer than the latest LTS:
| Scenario | Targets | Rationale |
|---|---|---|
| .NET 10 is current LTS | `net8.0;net10.0` | Skip .NET 9 (STS, superseded) |
| .NET 11 (STS) ships | `net8.0;net10.0;net11.0` | 11 > 10, include it |
| .NET 12 (LTS) ships | `net10.0;net12.0` | .NET 8 drops; 11 superseded |
Libraries with **no framework dependency** (no domain prefix) should also target `netstandard2.0`/`netstandard2.1` when APIs and dependencies allow. Framework-dependent libraries skip .NET Standard.
## Procedure
1. Ask the user for the library's purpose.
2. Propose name options using the naming table above.
3. Determine the correct multi-targeting based on current LTS/STS and framework dependencies.
4. Create the project under `src/{LibraryName}/`.
5. Do **not** specify `Version` on `PackageReference` — add versions in `Directory.Packages.props`.
6. Create a matching test project under `tests/{LibraryName}.Tests/`.
7. Add both projects to `Solution.slnx`.
8. Verify the build compiles cleanly.
+83
View File
@@ -0,0 +1,83 @@
---
name: new-release
description: 'Cut a new release: tag the appropriate commit, generate the changelog, and produce build artifacts. Use when: releasing a new version, tagging a release, publishing NuGet packages, preparing release artifacts.'
argument-hint: 'Branch or commit to release from (default: current main) and the kind of release (stable, prerelease, hotfix)'
---
# New Release
Versioning is **GitVersion-driven** (`GitVersion.yml`). Do not hand-pick versions — let GitVersion compute them from branch and tag history.
## Versioning
The root `GitVersion.yml` uses the `TrunkBased/preview1` workflow. Its `Mainline` strategy is what makes stable branches increment per commit rather than holding one version until the next tag.
| Branch | Label | Resulting version |
| --- | --- | --- |
| `main`, `release/*` | — | `MAJOR.MINOR.PATCH` (stable; **patch increments on every commit**) |
| `feature/*` | branch name | `…-<branch>.N` (pre-release; merging bumps **minor**) |
| `hotfix/*` | branch name | `…-<branch>.N` (pre-release; merging bumps **patch**) |
- Tags use the prefix `v` (regex `[vV]?` also accepts `V` or none).
- Each `src/*` project is versioned **independently**: only changes under that project's own directory, `Directory.Packages.props`, or `GitVersion.yml` increment its version (see `GenerateProjectGitVersionConfig` in `src/Directory.Build.props`, which renders the root `GitVersion.yml` into a per-project copy). A change to one library does not bump a sibling's version.
- All five packages still share one tag namespace, so a tag rebases every project's `MAJOR.MINOR` at once. Only the patch/pre-release counters diverge per project.
- Increments are suppressed on already-tagged commits, so the tagged commit builds exactly the tagged version.
## Changelog
Release notes are generated at pack time and embedded as `PackageReleaseNotes`. The `GenerateChangelogFromGit` target writes `git log` subjects to `$(ChangeLogPath)`, and `CreateReleaseNotesFromFile` reads that file into the nuspec. Both run before `GenerateNuspec`, and generation is skipped when the repository root has no `.git` directory.
The commit range is resolved in this order, first match wins:
1. `$(ChangeLogFromRef)..HEAD` — when `ChangeLogFromRef` is set.
2. `<tag>..HEAD` — from `git describe --tags --abbrev=0`.
3. `<sha>..HEAD` — the last first-parent merge whose subject matches `$(ChangeLogUpstreamMergePattern)`.
4. `<sha>..HEAD` — the last first-parent merge.
5. No range; the log is capped at `$(ChangeLogCommitLimit)` commits.
Commits are filtered with `--no-merges` and scoped to the project's own directory, plus the directories of its `ProjectReference`s unless `ChangeLogIncludeReferences` is `false`. This mirrors the per-project versioning rule above: a sibling library's commits do not appear in this package's notes.
| Property | Default | Purpose |
| --- | --- | --- |
| `ChangeLogFromRef` | *(empty)* | Explicit range start; overrides the fallback chain |
| `ChangeLogPath` | `$(BaseIntermediateOutputPath)changes.log` | Where the log is written and read from |
| `ChangeLogCommitLimit` | `100` | Cap used only when no range resolves |
| `ChangeLogUpstreamMergePattern` | `from .*/` | Subject matcher for the upstream-merge fallback |
| `ChangeLogIncludeReferences` | `true` | Include `ProjectReference` directories in scoping |
| `GenerateChangelogFromGit` | *(unset)* | Set to `false` to skip generation entirely |
> [!IMPORTANT]
> Step 2 uses the **nearest reachable** tag, not the newest. Packing from a commit that already carries a release tag therefore yields only the commits added since it — often a single entry. Pass `ChangeLogFromRef` to widen the range:
>
> ```shell
> dotnet pack -c Release -p:ChangeLogFromRef=v4.0.0
> ```
To ship hand-written notes instead, disable generation and point `ChangeLogPath` at your own file. Generation must be disabled, otherwise the target overwrites it:
```shell
dotnet pack -c Release -p:GenerateChangelogFromGit=false -p:ChangeLogPath=notes.md
```
Confirm the resolved range in the build output before publishing:
```text
Generated changelog at <path> using range v4.0.0..HEAD.
```
## Procedure
1. **Sync.** `git fetch --all --tags && git status` — confirm clean.
2. **Compute.** `dotnet build src\<Project>\<Project>.csproj -getProperty:Version` — verify the value matches expectations for that specific project (there is no single repo-wide version).
3. **Pack.** `dotnet pack -c Release` (or use the [docker-build](../docker-build/SKILL.md) `pack` target). Artifacts land in `artifacts/nuget/`. Check the logged changelog range and pass `ChangeLogFromRef` if it is narrower than the release warrants.
4. **Tag.** `git tag -a v<version> -m "Release v<version>" && git push origin v<version>`.
5. **Publish** packages to the configured feed.
6. **Create the GitHub release** linked to the tag, using the generated changelog as notes.
For hotfixes: branch from the latest stable tag (`git switch -c hotfix/<name> v<latest-stable>`), follow the procedure, then merge back into `main`. There is no `develop` branch to reconcile with — this repo is trunk-based.
## Guardrails
- **Tags are immutable** once pushed; never move or delete them.
- **Never skip a `PATCH`** — ship a fix forward.
- **Do not edit `GitVersion.yml` or a generated `src/*/GitVersion.yml` to force a version.** Address the underlying cause (missing tag, branch base, path filter, commit messages). Generated per-project files are gitignored build artifacts, re-derived from the root `GitVersion.yml` on every build — never hand-edit them.
@@ -0,0 +1,58 @@
---
name: new-web-api-project
description: 'Scaffold a new ASP.NET web project (API or worker service) with correct structure, launch settings, and Docker integration. Use when: creating a new web API, adding an ASP.NET project, setting up a new web service under src/.'
argument-hint: 'Brief description of the web project (e.g., "REST API for user management", "background worker for email processing")'
---
# New Web Project
## When to Use
- Creating a new ASP.NET web API or worker service under `src/`
- Adding a web project that will be deployed via Docker
## Procedure
1. Ask the user for the project's purpose and type (API or worker).
2. Create the project under `src/{ProjectName}/` using the appropriate SDK (`Microsoft.NET.Sdk.Web` or `Microsoft.NET.Sdk.Worker`).
4. **Single target framework** — web projects target only the current LTS (no multi-targeting).
5. Create `Properties/launchSettings.json` with `http` and `https` profiles:
- Pick ports that **do not conflict** with existing projects — check all `src/*/Properties/launchSettings.json` files first.
- Set `launchBrowser: false`.
- Set `ASPNETCORE_ENVIRONMENT: Development`.
6. For APIs: use **Minimal APIs** with OpenAPI support (`Microsoft.AspNetCore.OpenApi`). The OpenAPI document generation and Spectral linting are handled automatically by the build infrastructure.
7. Create a matching test project under `tests/{ProjectName}.Tests/`.
8. Add both projects to `Solution.slnx`.
9. Add a compose service entry to `compose.yaml` (or create one from `docker/compose.sample.yaml`):
- Set `RUNTIME_BASE: web` for APIs, `RUNTIME_BASE: app` for workers.
- Set `PUBLISHED_PROJECT` to the project name.
- Build context is the repo root with `dockerfile: docker/Dockerfile`.
10. Verify the build compiles cleanly.
## Launch Settings Template
```json
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:{HTTP_PORT}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "https://localhost:{HTTPS_PORT};http://localhost:{HTTP_PORT}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
```
+6
View File
@@ -1156,3 +1156,9 @@ artifacts/**
## Machine-specific overrides ## Machine-specific overrides
compose.override.yaml compose.override.yaml
## Generated per-project GitVersion config (rendered from the root GitVersion.yml)
src/*/GitVersion.yml
## Copilot agent scratch/research notes (ephemeral, not project documentation)
.copilot-tracking/
+2 -153
View File
@@ -3,10 +3,11 @@ is_global = true
# Ruleset replacement # Ruleset replacement
# C# compiler diagnostics # C# compiler diagnostics
dotnet_diagnostic.CS1573.severity = none # Missing XML comment for parameter dotnet_diagnostic.CS1573.severity = none # Missing XML comment for parameter
dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member dotnet_diagnostic.CS1591.severity = suggestion # Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS2008.severity = none # No source files specified dotnet_diagnostic.CS2008.severity = none # No source files specified
# Code quality analyzers # Code quality analyzers
dotnet_diagnostic.CA1515.severity = suggestion # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1515
dotnet_diagnostic.CA1303.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1303 dotnet_diagnostic.CA1303.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1303
dotnet_diagnostic.CA1707.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1707 dotnet_diagnostic.CA1707.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1707
dotnet_diagnostic.CA1848.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848 dotnet_diagnostic.CA1848.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848
@@ -19,155 +20,3 @@ dotnet_diagnostic.Serilog004.severity = none # Serilog context property accessor
dotnet_diagnostic.SA1101.severity = none # Prefix local calls with this dotnet_diagnostic.SA1101.severity = none # Prefix local calls with this
dotnet_diagnostic.SA1633.severity = none # File must have header dotnet_diagnostic.SA1633.severity = none # File must have header
dotnet_diagnostic.SA1649.severity = none # File name must match first type name dotnet_diagnostic.SA1649.severity = none # File name must match first type name
# Organize usings
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = true
csharp_using_directive_placement = inside_namespace:suggestion
csharp_prefer_simple_using_statement = true:suggestion
csharp_style_namespace_declarations = file_scoped:warning
# this. preferences
dotnet_style_qualification_for_field = false:none
dotnet_style_qualification_for_property = false:none
dotnet_style_qualification_for_method = false:none
dotnet_style_qualification_for_event = false:none
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_readonly_field = true:suggestion
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
###############################
# Naming Conventions #
###############################
# Style Definitions
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style
dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style
# Use PascalCase for constant fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
dotnet_naming_symbols.constant_fields.required_modifiers = const
###############################
# C# Coding Conventions #
###############################
# var preferences
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_methods = when_on_single_line :suggestion
csharp_style_expression_bodied_constructors = when_on_single_line :suggestion
csharp_style_expression_bodied_operators = when_on_single_line :suggestion
csharp_style_expression_bodied_properties = when_on_single_line :suggestion
csharp_style_expression_bodied_indexers = when_on_single_line :suggestion
csharp_style_expression_bodied_accessors = when_on_single_line :suggestion
csharp_style_expression_bodied_lambdas = when_on_single_line :suggestion
csharp_style_expression_bodied_local_functions = when_on_single_line :suggestion
# Pattern matching preferences
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
# Null-checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Expression-level preferences
csharp_prefer_braces = true:none
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
# Unused value preferences
csharp_style_unused_value_expression_statement_preference = discard_variable:none
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
## Index and Range preferences
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
###############################
# C# Formatting Rules #
###############################
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents_when_block = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_after_comma = true
csharp_space_before_comma = false
csharp_space_after_dot = false
csharp_space_before_dot = false
csharp_space_after_semicolon_in_for_statement = true
csharp_space_before_semicolon_in_for_statement = false
csharp_space_around_declaration_statements = false
csharp_space_before_open_square_brackets = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_statements = true
csharp_preserve_single_line_blocks = true
###############################
# VB Coding Conventions #
###############################
# Modifier preferences
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion
###############################
# Extra Rules #
###############################
# dotnet_naming_rule.private_constants_rule.severity = warning
# dotnet_naming_rule.private_constants_rule.style = upper_camel_case_style
# dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
# dotnet_naming_rule.private_instance_fields_rule.severity = warning
dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_style
# dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols
# dotnet_naming_rule.private_static_fields_rule.severity = warning
dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style
# dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols
# dotnet_naming_style.prefix_private_field_with_underscore.required_prefix = _
+10
View File
@@ -0,0 +1,10 @@
{
"recommendations": [
"EditorConfig.EditorConfig",
"mhutchie.git-graph",
"ms-dotnettools.csdevkit",
"ms-vscode-remote.remote-containers",
"seatonjiang.gitmoji-vscode",
"redhat.vscode-xml"
]
}
+20
View File
@@ -0,0 +1,20 @@
{
"json.schemas": [
{
"fileMatch": [
"xunit.runner.json"
],
"url": "https://xunit.net/schema/current/xunit.runner.schema.json"
},
{
"fileMatch": [
"stylecop.json"
],
"url": "https://raw.githubusercontent.com/bjornhellander/NewStyleCopAnalyzers/refs/heads/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json"
}
],
"editor.wordWrap": "on",
"[xml]": {
"editor.defaultFormatter": "redhat.vscode-xml"
}
}
+13 -27
View File
@@ -10,6 +10,7 @@
<NoLogo>true</NoLogo> <NoLogo>true</NoLogo>
<!-- Prepend organization name to default namespace --> <!-- Prepend organization name to default namespace -->
<RootNamespace>Kritikos.$(MSBuildProjectName)</RootNamespace> <RootNamespace>Kritikos.$(MSBuildProjectName)</RootNamespace>
<AssemblyName>Kritikos.$(MSBuildProjectName)</AssemblyName>
<!-- Enable global usings based on project type --> <!-- Enable global usings based on project type -->
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<!-- Generate documentation file and ignore warnings for undocumented elements --> <!-- Generate documentation file and ignore warnings for undocumented elements -->
@@ -49,8 +50,13 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<!-- Defaults to checked context for math operations, throws OverflowException when needed --> <!-- Defaults to unchecked context for math operations for performance -->
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> <!-- set to true to throws OverflowException when needed -->
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Label="OpenApi Source Generated Interceptors">
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.OpenApi.Generated</InterceptorsNamespaces>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="$(ArtifactsPath) == '' AND $(DisableCustomArtifactsPath) != 'true'"> <PropertyGroup Condition="$(ArtifactsPath) == '' AND $(DisableCustomArtifactsPath) != 'true'">
@@ -74,20 +80,12 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Project Assets"> <PropertyGroup Label="Project Assets">
<ProjectIcon Condition="Exists('$(MSBuildThisFileDirectory)\icon.png')"> <ProjectIcon Condition="Exists('$(MSBuildThisFileDirectory)icon.png')">$(MSBuildThisFileDirectory)icon.png</ProjectIcon>
$(MSBuildThisFileDirectory)icon.png <ProjectIcon Condition="Exists('$(MSBuildProjectDirectory)\icon.png')">$(MSBuildProjectDirectory)\icon.png</ProjectIcon>
</ProjectIcon>
<ProjectIcon Condition="Exists('$(MSBuildProjectDirectory)\icon.png')">
$(MSBuildProjectDirectory)icon.png
</ProjectIcon>
<ProjectIconExists Condition="$(ProjectIcon) != ''">true</ProjectIconExists> <ProjectIconExists Condition="$(ProjectIcon) != ''">true</ProjectIconExists>
<ProjectReadMe Condition="Exists('$(MSBuildThisFileDirectory)\README.md')"> <ProjectReadMe Condition="Exists('$(MSBuildThisFileDirectory)README.md')">$(MSBuildThisFileDirectory)README.md</ProjectReadMe>
$(MSBuildThisFileDirectory)README.md <ProjectReadMe Condition="Exists('$(MSBuildProjectDirectory)\README.md')">$(MSBuildProjectDirectory)\README.md</ProjectReadMe>
</ProjectReadMe>
<ProjectReadMe Condition="Exists('$(MSBuildProjectDirectory)\README.md')">
$(MSBuildProjectDirectory)README.md
</ProjectReadMe>
<ProjectReadMeExists Condition="$(ProjectReadMe) != ''">true</ProjectReadMeExists> <ProjectReadMeExists Condition="$(ProjectReadMe) != ''">true</ProjectReadMeExists>
</PropertyGroup> </PropertyGroup>
@@ -122,11 +120,6 @@
<EFOptimizeContext>true</EFOptimizeContext> <EFOptimizeContext>true</EFOptimizeContext>
</PropertyGroup> </PropertyGroup>
<!-- Mark assemblies as CLS compliant so the compiler warns on non compliant usage -->
<PropertyGroup Condition="$(IsPackable) == 'true'">
<ClsCompliant>true</ClsCompliant>
<GenerateSBOM>true</GenerateSBOM>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="System.CLSCompliant"> <AssemblyAttribute Include="System.CLSCompliant">
<_Parameter1>$(ClsCompliant)</_Parameter1> <_Parameter1>$(ClsCompliant)</_Parameter1>
@@ -154,13 +147,6 @@
CopyToOutputDirectory="Never" Visible="false" /> CopyToOutputDirectory="Never" Visible="false" />
</ItemGroup> </ItemGroup>
<!-- Project internals are exposed to projects named $(Project).Tests by default -->
<ItemGroup
Condition="@(InternalsVisibleToSuffix->Count()) == 0 AND @(InternalsVisibleTo->Count()) == 0">
<InternalsVisibleToSuffix Include=".Tests" />
<InternalsVisibleToSuffix Include="Tests" />
</ItemGroup>
<PropertyGroup Label="Package"> <PropertyGroup Label="Package">
<PackageId>$(RootNamespace)</PackageId> <PackageId>$(RootNamespace)</PackageId>
<Company>Kritikos IO</Company> <Company>Kritikos IO</Company>
@@ -178,7 +164,7 @@
<EnablePackageValidation>true</EnablePackageValidation> <EnablePackageValidation>true</EnablePackageValidation>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression> <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Versioning" Condition="'$(IsTestProject)' != 'true'"> <ItemGroup Label="Versioning" Condition="'$(IsTestProject)' != 'true'">
+58 -23
View File
@@ -9,8 +9,14 @@
<None Update="packages.lock.json" Visible="false" /> <None Update="packages.lock.json" Visible="false" />
</ItemGroup> </ItemGroup>
<PropertyGroup>
<ClsCompliant Condition="'$(SkipClsCompliant)' != 'true' AND '$(IsPackable)' != 'false' AND '$(IsTestProject)' != 'true'">true</ClsCompliant>
<ClsCompliant Condition="'$(ClsCompliant)' == ''">false</ClsCompliant>
<GenerateSBOM Condition="'$(IsPackable)' != 'false' AND '$(IsTestProject)' != 'true'">true</GenerateSBOM>
</PropertyGroup>
<ItemGroup <ItemGroup
Condition="@(PackageReference->WithMetadataValue('Identity','Microsoft.AspNetCore.OpenApi')->Count()) &gt; 0"> Condition="'$(UsingMicrosoftNETSdkWeb)' == 'True' AND @(PackageReference->WithMetadataValue('Identity','Microsoft.AspNetCore.OpenApi')->Count()) &gt; 0">
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server"> <PackageReference Include="Microsoft.Extensions.ApiDescription.Server">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -29,40 +35,69 @@
AfterTargets="GenerateOpenApiDocuments" AfterTargets="GenerateOpenApiDocuments"
Condition="'$(OpenApiDocumentsDirectory)' != ''"> Condition="'$(OpenApiDocumentsDirectory)' != ''">
<Move SourceFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json" <Move SourceFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json"
DestinationFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName)-v1.json" DestinationFiles="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName)_v1.json"
Condition="Exists('$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json')" /> Condition="Exists('$(OpenApiDocumentsDirectory)/$(MSBuildProjectName).json')" />
</Target> </Target>
<!--
OpenApiDocumentsDirectory tracks $(ArtifactsPath), which developers may override to a
machine-specific location. Client generators (e.g. a checked-in .refitter file) need a
stable, repo-relative path, so mirror the renamed document(s) into the repo's own
artifacts/OpenApi folder regardless of where ArtifactsPath actually points.
Uses a glob (not a single "_v1.json" name) because a project may define multiple named
OpenAPI documents (AddOpenApi("v1"), AddOpenApi("v2"), ...), each emitted as its own
"$(MSBuildProjectName)_{documentName}.json" file.
-->
<Target Name="CopyOpenApiDocumentsToRepoArtifacts"
AfterTargets="RenameOpenApiDocuments"
Condition="'$(OpenApiDocumentsDirectory)' != ''">
<ItemGroup>
<OpenApiDocumentToCopy Include="$(OpenApiDocumentsDirectory)/$(MSBuildProjectName)*.json" />
</ItemGroup>
<Copy SourceFiles="@(OpenApiDocumentToCopy)"
DestinationFolder="$(MSBuildThisFileDirectory)artifacts/OpenApi"
SkipUnchangedFiles="true"
Condition="@(OpenApiDocumentToCopy->Count()) &gt; 0" />
</Target>
<Target Name="AddInternalsVisibleTo" BeforeTargets="BeforeCompile"> <Target Name="AddInternalsVisibleTo" BeforeTargets="BeforeCompile">
<!-- <!--
Add an ItemGroup with tags in the following format: Exposes assembly internals to friend assemblies.
<InternalsVisibleTo Include="CustomTest1" />
-> [assembly: InternalsVisibleTo("CustomTest1")]
<InternalsVisibleTo Include="CustomTest2, PublicKey=abc" />
-> [assembly: InternalsVisibleTo("CustomTest2, PublicKey=abc")]
<InternalsVisibleTo Include="$(AssemblyName).Custom" />
-> [assembly: InternalsVisibleTo("ClassLibrary1.Custom")]
on a project with assembly name ClasLibrary1: The .NET SDK already turns <InternalsVisibleTo Include="..." /> items into
<InternalsVisibleToSuffix Include=".Tests" /> [assembly: InternalsVisibleTo("...")] attributes in its GetAssemblyAttributes
target (including strong-name PublicKey handling via PublicKey/Key metadata).
This target must therefore NOT emit those attributes itself - doing so emits
every friend assembly twice.
Instead it only layers the project-local convention on top of the SDK:
* translate <InternalsVisibleToSuffix> entries into InternalsVisibleTo items
so the SDK can emit them, and
* apply a sensible default when a project declared no friend assemblies.
Examples on an assembly named "ClassLibrary1":
<InternalsVisibleTo Include="CustomTest1" /> (handled by the SDK)
-> [assembly: InternalsVisibleTo("CustomTest1")]
<InternalsVisibleToSuffix Include=".Tests" /> (handled here)
-> [assembly: InternalsVisibleTo("ClassLibrary1.Tests")] -> [assembly: InternalsVisibleTo("ClassLibrary1.Tests")]
<InternalsVisibleToSuffix Include=".FunctionalTests" />
-> [assembly: InternalsVisibleTo("ClassLibrary1.FunctionalTests")] Running at build time (before GetAssemblyAttributes) means the counts below
see items declared in both imported props and the project body, so an
explicit InternalsVisibleTo correctly suppresses the default suffix.
--> -->
<!-- Handle InternalsVisibleTo --> <!-- Default: expose internals to "<AssemblyName>.Tests" when the project has
<ItemGroup Condition="'@(InternalsVisibleTo->Count())' &gt; 0"> not declared any friend assemblies of its own. -->
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> <ItemGroup Condition="@(InternalsVisibleTo->Count()) == 0 AND @(InternalsVisibleToSuffix->Count()) == 0">
<_Parameter1>%(InternalsVisibleTo.Identity)</_Parameter1> <InternalsVisibleToSuffix Include=".Tests" />
</AssemblyAttribute>
</ItemGroup> </ItemGroup>
<!-- Handle InternalsVisibleToSuffix --> <!-- Translate the suffix convention into InternalsVisibleTo items for the SDK,
skipping the current assembly (e.g. a "*.Tests" project itself). -->
<ItemGroup Condition="@(InternalsVisibleToSuffix->Count()) &gt; 0"> <ItemGroup Condition="@(InternalsVisibleToSuffix->Count()) &gt; 0">
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" <InternalsVisibleTo Include="$(AssemblyName)%(InternalsVisibleToSuffix.Identity)"
Condition="$(AssemblyName.EndsWith(%(InternalsVisibleToSuffix.Identity))) == 'false'"> Condition="$(AssemblyName.EndsWith(%(InternalsVisibleToSuffix.Identity))) == 'false'" />
<_Parameter1>$(AssemblyName)%(InternalsVisibleToSuffix.Identity)</_Parameter1>
</AssemblyAttribute>
</ItemGroup> </ItemGroup>
</Target> </Target>
+2 -2
View File
@@ -1,9 +1,9 @@
<Project> <Project>
<ItemGroup Label="Packages"> <ItemGroup Label="Packages">
<PackageVersion Include="GitVersion.MsBuild" Version="6.6.2" /> <PackageVersion Include="GitVersion.MsBuild" Version="6.8.2" />
<PackageVersion Include="Microsoft.Sbom.Targets" Version="4.1.5" /> <PackageVersion Include="Microsoft.Sbom.Targets" Version="4.1.5" />
<PackageVersion Include="NewStyleCop.Analyzers" Version="1.2.1" /> <PackageVersion Include="NewStyleCop.Analyzers" Version="1.2.1" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" /> <PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
<PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.5" /> <PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.10" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+31 -11
View File
@@ -1,26 +1,46 @@
workflow: GitHubFlow/v1 workflow: TrunkBased/preview1
mode: ContinuousDelivery
tag-prefix: '[vV]?' tag-prefix: '[vV]?'
ignore: ignore:
paths: paths:
- ^(?!src\/|Directory\.Packages\.props|GitVersion.yml).* - ^(?!src\/|Directory\.Packages\.props|GitVersion.yml).*
branches: branches:
develop: release:
label: 'beta' mode: ContinuousDeployment
regex: '^(dev|develop|development)$' label: ''
increment: Patch
regex: ^releases?[\/-](?<BranchName>.+)
source-branches: source-branches:
- main - main
feature: is-release-branch: true
is-main-branch: true
pre-release-weight: 55000
develop:
mode: ContinuousDelivery mode: ContinuousDelivery
label: alpha
increment: Minor
regex: ^develop$
source-branches: source-branches:
- main
prevent-increment:
when-current-commit-tagged: false
pre-release-weight: 0
feature:
source-branches:
- main
- develop - develop
- release
hotfix: hotfix:
regex: ^hotfix?[\/-](?<BranchName>.+) source-branches:
mode: ContinuousDelivery - main
release: - release
mode: ContinuousDelivery pull-request:
source-branches:
- main
- develop
- release
- feature
- hotfix
prevent-increment: prevent-increment:
of-merged-branch: true of-merged-branch: true
when-branch-merged: true
when-current-commit-tagged: true when-current-commit-tagged: true
+5 -28
View File
@@ -4,39 +4,16 @@
"path": "." "path": "."
} }
], ],
"extensions": {
"recommendations": [
"EditorConfig.EditorConfig",
"mhutchie.git-graph",
"ms-dotnettools.csdevkit",
"ms-vscode-remote.remote-containers",
"seatonjiang.gitmoji-vscode",
"redhat.vscode-xml"
]
},
"settings": { "settings": {
"files.associations": { "files.associations": {
"nuget.config": "xml" "nuget.config": "xml"
}, },
"json.schemas": [
{
"fileMatch": [
"xunit.runner.json"
],
"url": "https://xunit.net/schema/current/xunit.runner.schema.json"
},
{
"fileMatch": [
"stylecop.json"
],
"url": "https://raw.githubusercontent.com/bjornhellander/NewStyleCopAnalyzers/refs/heads/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json"
}
],
"editor.wordWrap": "on",
"[xml]": {
"editor.defaultFormatter": "redhat.vscode-xml"
},
"xml.format.maxLineWidth": 0, "xml.format.maxLineWidth": 0,
"xml.format.splitAttributes": "preserve", "xml.format.splitAttributes": "preserve",
"github.copilot.chat.commitMessageGeneration.instructions": [
{
"file": ".github/copilot-commit-message-instructions.md"
}
]
} }
} }
+1 -79
View File
@@ -1,4 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/DebuggerStepThroughAccessors/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/DebuggerStepThroughAccessors/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeEditing/GenerateMemberBody/DocumentationGenerationKind/@EntryValue">Inherit</s:String> <s:String x:Key="/Default/CodeEditing/GenerateMemberBody/DocumentationGenerationKind/@EntryValue">Inherit</s:String>
<s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/PlaceBackingFieldAboveProperty/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeEditing/GenerateMemberBody/PlaceBackingFieldAboveProperty/@EntryValue">True</s:Boolean>
@@ -14,14 +14,8 @@
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAtOtherPositions/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsEnabledAtOtherPositions/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsInsertNullCheckWhenAlreadyAnnotated/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeEditing/TypingAssist/CSharpAnnotationTypingAssist/IsInsertNullCheckWhenAlreadyAnnotated/@EntryValue">False</s:Boolean>
<s:Int64 x:Key="/Default/CodeInspection/CognitiveComplexityAnalysis/CSharpThreshold/@EntryValue">20</s:Int64>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=_002AModelSnapshot_002Ecs/@EntryIndexedValue">*ModelSnapshot.cs</s:String>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=Migrations_002F_002A/@EntryIndexedValue">Migrations/*</s:String>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/CalculateInheritedTypeMembers/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Highlighting/CalculateInheritedTypeMembers/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/DoNotShowVsBulb/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Highlighting/DoNotShowVsBulb/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ClassNeverInstantiated_002ELocal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConvertToPrimaryConstructor/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/MergeVsBulbItemsIntoReSharperBulb/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Highlighting/MergeVsBulbItemsIntoReSharperBulb/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/ReadSettingsFromFileLevel/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/Highlighting/ReadSettingsFromFileLevel/@EntryValue">True</s:Boolean>
@@ -29,83 +23,12 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">ShowAndRun</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">ShowAndRun</s:String>
<s:String x:Key="/Default/CodeInspection/XmlDocInspections/TypeAccessibility/@EntryValue">None</s:String> <s:String x:Key="/Default/CodeInspection/XmlDocInspections/TypeAccessibility/@EntryValue">None</s:String>
<s:String x:Key="/Default/CodeInspection/XmlDocInspections/TypeMemberAccessibility/@EntryValue">None</s:String> <s:String x:Key="/Default/CodeInspection/XmlDocInspections/TypeMemberAccessibility/@EntryValue">None</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CommonFormatter/AUTODETECT_INDENT_SETTINGS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALIGNMENT_TAB_FILL_STYLE/@EntryValue">USE_SPACES</s:String>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_REGION/@EntryValue">0</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_SINGLE_LINE_COMMENT/@EntryValue">1</s:Int64>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BETWEEN_USING_GROUPS/@EntryValue">1</s:Int64>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSOR_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_WHILE_ON_NEW_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_BEFORE_BINARY_OPSIGN/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_CHAINED_METHOD_CALLS/@EntryValue">CHOP_IF_LONG</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINQ_EXPRESSIONS/@EntryValue">CHOP_ALWAYS</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_TERNARY_EXPR_STYLE/@EntryValue">CHOP_ALWAYS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CSharpUsing/QualifiedUsingAtNestedScope/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/EnableStyleCopSupport/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/EditorConfig/EnableStyleCopSupport/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/EditorConfig/ShowEditorConfigStatusBarIndicator/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/EditorConfig/ShowEditorConfigStatusBarIndicator/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCLASS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FCONSTRUCTOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMIXED_005FENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FALIAS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CustomTools/CustomToolsData/@EntryValue"></s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=AutoRecoverer/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=Format/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=Roslyn_002Dswea/@EntryIndexedValue">DO_NOTHING</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=ShowAnnotations/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=SolExp_002DTrack/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=StartPage_002DIsDownloadRefreshEnabled/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=StartPage_002DOnEnvironmentStatup/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=SyncSettings/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=TextEditor_002DCodeLens/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=TextEditor_002DTrackChanges_002D2/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=VCS/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=VsBulb/@EntryIndexedValue">DO_NOTHING</s:String>
<s:String x:Key="/Default/Environment/PerformanceGuide/SwitchBehaviour/=XAML_0020Designer/@EntryIndexedValue">LIVE_MONITOR</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
@@ -115,6 +38,5 @@
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=Testing_0020Platform/@EntryIndexedValue">False</s:Boolean> <s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=Testing_0020Platform/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=VsTest/@EntryIndexedValue">False</s:Boolean> <s:Boolean x:Key="/Default/Environment/UnitTesting/DisabledProviders/=VsTest/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/UnitTesting/TestingPlatformTestProvider/IgnoreProjectsSupportedByOtherProviders/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/Environment/UnitTesting/TestingPlatformTestProvider/IgnoreProjectsSupportedByOtherProviders/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/ReSpeller/ReSpellerEnabled/@EntryValue">False</s:Boolean>
</wpf:ResourceDictionary> </wpf:ResourceDictionary>
+1 -1
View File
@@ -6,7 +6,7 @@
<PropertyGroup> <PropertyGroup>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<IsPublishable>false</IsPublishable> <IsPublishable>false</IsPublishable>
<NoWarn>$(NoWarn);SA1600</NoWarn> <NoWarn>$(NoWarn);SA1600;SA1601;CS1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+72 -2
View File
@@ -1,9 +1,79 @@
<Project> <Project>
<ImportGroup Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))) == 'true'"> <ImportGroup
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" /> Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))) == 'true'">
<Import
Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="Package"> <PropertyGroup Label="Package">
<PackageProjectUrl>http://localhost</PackageProjectUrl> <PackageProjectUrl>http://localhost</PackageProjectUrl>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="GitVersion per-project scoping">
<GitVersionTemplateFile>$(MSBuildThisFileDirectory)..\GitVersion.yml</GitVersionTemplateFile>
<_GitVersionIgnorePathsRegex>(paths:\s*\r?\n\s*- ).+</_GitVersionIgnorePathsRegex>
</PropertyGroup>
<!--
GitVersion.MsBuild runs `gitversion "$(MSBuildProjectDirectory)"`, and GitVersion resolves its
config by
walking up from that directory to the repo root, using the first GitVersion.yml it finds. Rendering
one
here (rewriting the repo-root GitVersion.yml's ignore.paths entry, so there is a single
hand-maintained
file) scopes ignore.paths to this project's own directory plus the full transitive closure of its
ProjectReference dependencies, so a change anywhere upstream in the dependency graph also counts
toward
this project's version. Generated file is gitignored (see .gitignore).
-->
<Target Name="_CollectGitVersionTransitiveReferences" Returns="@(_GitVersionTransitiveRef)">
<ItemGroup>
<!-- Resolve to FullPath here, before crossing the MSBuild task-output boundary below:
relative
Includes from an intermediate project resolve against the wrong directory once passed through. -->
<_GitVersionTransitiveRef Include="@(ProjectReference->'%(FullPath)')" />
</ItemGroup>
<MSBuild Projects="@(ProjectReference)" Targets="_CollectGitVersionTransitiveReferences"
Condition="'@(ProjectReference)' != ''" SkipNonexistentTargets="true">
<Output TaskParameter="TargetOutputs" ItemName="_GitVersionTransitiveRef" />
</MSBuild>
</Target>
<Target Name="GenerateProjectGitVersionConfig" BeforeTargets="RunGitVersion"
Condition="Exists('$(GitVersionTemplateFile)')">
<MSBuild Projects="$(MSBuildProjectFullPath)" Targets="_CollectGitVersionTransitiveReferences"
Condition="'@(ProjectReference)' != ''" SkipNonexistentTargets="true">
<Output TaskParameter="TargetOutputs" ItemName="_GitVersionScopeProjectRef" />
</MSBuild>
<ItemGroup>
<_GitVersionScopePath Include="$(MSBuildProjectDirectory)" />
<_GitVersionScopePath Include="@(_GitVersionScopeProjectRef->'%(RootDir)%(Directory)')" />
</ItemGroup>
<ItemGroup>
<_GitVersionScopePath>
<EscapedPath>$([MSBuild]::EnsureTrailingSlash($([MSBuild]::MakeRelative('$(MSBuildThisFileDirectory)..\',
'%(Identity)'))).Replace('\', '/').Replace('.', '\.').Replace('/', '\/'))</EscapedPath>
</_GitVersionScopePath>
</ItemGroup>
<PropertyGroup>
<_GitVersionIgnorePattern>^(?!@(_GitVersionScopePath->'%(EscapedPath)',
'|')|Directory\.Packages\.props|GitVersion\.yml).*</_GitVersionIgnorePattern>
<_GitVersionTemplateContent>$([System.IO.File]::ReadAllText('$(GitVersionTemplateFile)'))</_GitVersionTemplateContent>
<_GitVersionRenderedContent>$([System.Text.RegularExpressions.Regex]::Replace('$(_GitVersionTemplateContent)',
'$(_GitVersionIgnorePathsRegex)', '$1$(_GitVersionIgnorePattern)'))</_GitVersionRenderedContent>
</PropertyGroup>
<Error Condition="'$(_GitVersionRenderedContent)' == '$(_GitVersionTemplateContent)'"
Text="GenerateProjectGitVersionConfig: could not find an ignore.paths entry to rewrite in $(GitVersionTemplateFile) for $(MSBuildProjectName) -- check its ignore.paths structure." />
<WriteLinesToFile File="$(MSBuildProjectDirectory)\GitVersion.yml"
Lines="$(_GitVersionRenderedContent)"
Overwrite="true" WriteOnlyWhenDifferent="true" />
</Target>
<PropertyGroup Label="Changelog per-project scoping">
<!-- GenerateChangelogFromGit (root Directory.Build.targets) walks direct ProjectReference
directories when this is true. A dependency's own changes belong in its own changelog/version,
not copied here (that would misattribute a dependency's commit as this project's own change):
scope to this project's own directory only. -->
<ChangeLogIncludeReferences>false</ChangeLogIncludeReferences>
</PropertyGroup>
</Project> </Project>
+21
View File
@@ -0,0 +1,21 @@
<Project>
<ImportGroup
Condition="Exists($([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))) == 'true'">
<Import
Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
</ImportGroup>
<!-- Overrides the root's CreateReleaseNotesFromFile: its Condition="Exists('$(ChangeLogPath)')" is
evaluated before its own DependsOnTargets="GenerateChangelogFromGit" has run, so on a clean build the file
never exists yet and PackageReleaseNotes silently never gets set. Moving the existence check onto the
task (evaluated after the dependency runs) instead of the target fixes the ordering. -->
<Target Name="CreateReleaseNotesFromFile" BeforeTargets="GenerateNuspec"
DependsOnTargets="GenerateChangelogFromGit">
<ReadLinesFromFile File="$(ChangeLogPath)" Condition="Exists('$(ChangeLogPath)')">
<Output TaskParameter="Lines" ItemName="ReleaseNoteLines" />
</ReadLinesFromFile>
<PropertyGroup Condition="Exists('$(ChangeLogPath)')">
<PackageReleaseNotes>@(ReleaseNoteLines, '%0a')</PackageReleaseNotes>
</PropertyGroup>
</Target>
</Project>
+1 -1
View File
@@ -6,7 +6,7 @@
<PropertyGroup> <PropertyGroup>
<IsPublishable>false</IsPublishable> <IsPublishable>false</IsPublishable>
<IsTestProject>true</IsTestProject> <IsTestProject>true</IsTestProject>
<NoWarn>$(NoWarn);SA1600</NoWarn> <NoWarn>$(NoWarn);SA1600;SA1601;CS1591</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="xUnit Configuration" Condition="Exists('$(MSBuildThisFileDirectory)\..\xunit.runner.json') AND $(IsTestProject)=='True' AND @(PackageReference->StartsWith('xunit')->Count()) &gt; 0"> <ItemGroup Label="xUnit Configuration" Condition="Exists('$(MSBuildThisFileDirectory)\..\xunit.runner.json') AND $(IsTestProject)=='True' AND @(PackageReference->StartsWith('xunit')->Count()) &gt; 0">