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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .claude/commands/coreex-docs-sync.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
description: "Fetch the CoreEx sample architecture docs and all per-package AI usage guides from GitHub and cache them locally under .github/docs/coreex/ for offline, faster expert guidance."
allowed-tools: [Read, Write, Glob, Grep, WebFetch]
---

Sync the CoreEx docs to `.github/docs/coreex/`. Follow these steps exactly.

## Step 1 — Detect current CoreEx version

Search for the `CoreEx` NuGet package version in this order, stopping at the first match:
1. `Directory.Packages.props` — look for `<PackageVersion Include="CoreEx" Version="..." />`
2. Any `*.csproj` file — look for `<PackageReference Include="CoreEx" Version="..." />`
3. `Directory.Build.props`

Record the version (or `unknown` if not found). Use it in the manifest.

## Step 2 — Detect referenced CoreEx packages (for manifest only)

Scan `Directory.Packages.props` and all `*.csproj` files for `PackageVersion` or `PackageReference` entries whose `Include` attribute starts with `CoreEx`. Collect the distinct package names. This list goes into the manifest so the CoreEx Expert knows which packages the project currently uses — it does not limit which guides are synced.

## Step 3 — Create cache directories

Ensure both directories exist. Create them if absent:
- `.github/docs/coreex/`
- `.github/docs/coreex/agents/`

## Step 4 — Fetch and write the sample architecture docs

Fetch each URL below and write to the corresponding local path. Report each as it completes.

| URL | Local path |
|---|---|
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/local-dev.md` | `.github/docs/coreex/local-dev.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/layers.md` | `.github/docs/coreex/layers.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/patterns.md` | `.github/docs/coreex/patterns.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/contracts-layer.md` | `.github/docs/coreex/contracts-layer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/domain-layer.md` | `.github/docs/coreex/domain-layer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/application-layer.md` | `.github/docs/coreex/application-layer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/infrastructure-layer.md` | `.github/docs/coreex/infrastructure-layer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/hosts-layer.md` | `.github/docs/coreex/hosts-layer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/testing.md` | `.github/docs/coreex/testing.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/tooling.md` | `.github/docs/coreex/tooling.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/samples/docs/aspire.md` | `.github/docs/coreex/aspire.md` |

## Step 5 — Fetch and write all per-package guides

Fetch the `AGENTS.md` for every CoreEx package listed below — regardless of whether the project currently references them. This allows the CoreEx Expert to guide on and recommend any package, including ones not yet adopted.

| URL | Local path |
|---|---|
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.AspNetCore/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.AspNetCore.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.AspNetCore.NSwag/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.AspNetCore.NSwag.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Azure.Messaging.ServiceBus/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Azure.Messaging.ServiceBus.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Caching.FusionCache/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Caching.FusionCache.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.CodeGen/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.CodeGen.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Data/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Data.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Database/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Database.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Database.Postgres/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Database.Postgres.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Database.SqlServer/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Database.SqlServer.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.DomainDriven/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.DomainDriven.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.EntityFrameworkCore/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.EntityFrameworkCore.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Events/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Events.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.RefData/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.RefData.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.UnitTesting/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.UnitTesting.md` |
| `https://raw.githubusercontent.com/Avanade/CoreEx/main/src/CoreEx.Validation/AGENTS.md` | `.github/docs/coreex/agents/CoreEx.Validation.md` |

If any fetch fails, record the failure, skip that file, and continue.

## Step 6 — Write the manifest

Write `.github/docs/coreex/.manifest` with this exact format:

```
synced: YYYY-MM-DD
coreex-version: <version from Step 1, or "unknown">
referenced-packages: <comma-separated list of packages detected in Step 2, or "none detected">
```

## Step 7 — Report

Summarise:
- How many architecture docs were written successfully.
- How many package guides were written successfully (out of 16).
- Any files that failed to fetch (with the error).
- The CoreEx version and referenced packages recorded in the manifest.
- A reminder: *"Re-run `/coreex-docs-sync` after bumping the CoreEx NuGet version or when the CoreEx Expert suggests the cache is stale."*
8 changes: 8 additions & 0 deletions .claude/commands/coreex-expert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
description: "CoreEx Expert — architecture guidance, pattern decisions, and sample-aligned advice for projects using CoreEx NuGet packages."
allowed-tools: [Read, Glob, Grep, WebFetch, WebSearch, Edit, Write]
---

Read `.github/agents/coreex-expert.agent.md` and follow the instructions in that file.

The user's question or request follows. Apply the CoreEx Expert role, operating rules, and response format defined in the agent file.
193 changes: 188 additions & 5 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,13 +1,196 @@
root = true

# ── Universal ────────────────────────────────────────────────────────────────

[*]
indent_style = space
indent_size = 4
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = false
insert_final_newline = true

# ── C# source files ──────────────────────────────────────────────────────────

[*.cs]
indent_style = space
indent_size = 4
indent_size = 4

# ── Formatting ───────────────────────────────────────────────────────────────

# Allman-style braces — opening brace always on its own line.
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
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left

# Spacing
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_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

# Wrapping
csharp_preserve_single_line_statements = false
csharp_preserve_single_line_blocks = true

# Using directives — System.* first; no blank lines between groups.
dotnet_sort_system_directives_first = false
dotnet_separate_import_directive_groups = false
Comment on lines +47 to +49

# ── Language rules — standards (IDE warning; not a build error without EnforceCodeStyleInBuild) ──

# File-scoped namespaces required.
csharp_style_namespace_declarations = file_scoped:warning

# Null-forgiving operator: prefer is-null checks over reference equality.
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning

# ── Language rules — modernisation (IDE suggestion) ──────────────────────────

# Braces: omit on single-line if/else/for/while bodies; require when multi-line.
csharp_prefer_braces = when_multiline:none

# Expression-bodied members: prefer => when the entire body is a single expression.
csharp_style_expression_bodied_methods = when_on_single_line:none
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_accessors = when_on_single_line:none
csharp_style_expression_bodied_indexers = when_on_single_line:none
csharp_style_expression_bodied_operators = when_on_single_line:none
csharp_style_expression_bodied_lambdas = when_on_single_line:none
csharp_style_expression_bodied_local_functions = when_on_single_line:none
csharp_style_expression_bodied_constructors = when_on_single_line:none

# var: prefer explicit type for built-ins; prefer var when type is obvious from RHS.
csharp_style_var_for_built_in_types = false:none
csharp_style_var_when_type_is_apparent = true:none
csharp_style_var_elsewhere = true:none

# Null handling and pattern matching.
dotnet_style_null_propagation = true:none
dotnet_style_coalesce_expression = true:none
csharp_style_prefer_null_check_over_type_check = true:none
csharp_style_prefer_is_not_expression = true:none
csharp_style_prefer_pattern_matching = true:none
csharp_style_prefer_switch_expression = true:none

# Object and collection initialisers.
dotnet_style_object_initializer = true:none
dotnet_style_collection_initializer = true:none

# Modern using declarations (using var x = ... instead of using (var x = ...)).
csharp_prefer_simple_using_statement = true:none

# Auto-properties over explicit backing fields where no extra logic exists.
dotnet_style_prefer_auto_properties = true:none

# Throw expressions (x ?? throw ...).
csharp_style_throw_expression = true:none

# Conditional delegate invocation (handler?.Invoke() vs if (handler != null) handler()).
csharp_style_conditional_delegate_call = true:none

# Tuple/anonymous type member names.
dotnet_style_prefer_inferred_tuple_names = true:none
dotnet_style_prefer_inferred_anonymous_type_member_names = true:none

# Accessibility modifiers — always explicit, even when the default would apply.
dotnet_style_require_accessibility_modifiers = for_non_interface_members:none

# Preferred modifier order.
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:none

# ── Naming conventions ───────────────────────────────────────────────────────
# Rules are evaluated top-to-bottom; the first match wins.

## Symbol groups

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private,private_protected

dotnet_naming_symbols.non_private_fields.applicable_kinds = field
dotnet_naming_symbols.non_private_fields.applicable_accessibilities = public,internal,protected,protected_internal

dotnet_naming_symbols.constants.applicable_kinds = field,local
dotnet_naming_symbols.constants.required_modifiers = const

dotnet_naming_symbols.interfaces.applicable_kinds = interface

dotnet_naming_symbols.type_parameters.applicable_kinds = type_parameter

dotnet_naming_symbols.async_methods.applicable_kinds = method
dotnet_naming_symbols.async_methods.required_modifiers = async

## Naming styles

# _camelCase
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _

# PascalCase
dotnet_naming_style.pascal_case.capitalization = pascal_case

# IPascalCase
dotnet_naming_style.i_prefix_pascal_case.capitalization = pascal_case
dotnet_naming_style.i_prefix_pascal_case.required_prefix = I

# TPascalCase
dotnet_naming_style.t_prefix_pascal_case.capitalization = pascal_case
dotnet_naming_style.t_prefix_pascal_case.required_prefix = T

# PascalCaseAsync
dotnet_naming_style.pascal_case_async.capitalization = pascal_case
dotnet_naming_style.pascal_case_async.required_suffix = Async

## Rules

# Private fields → _camelCase (warning — agreed standard)
dotnet_naming_rule.private_fields_underscore.symbols = private_fields
dotnet_naming_rule.private_fields_underscore.style = prefix_underscore
dotnet_naming_rule.private_fields_underscore.severity = warning

# Non-private fields → PascalCase (suggestion — rare in this codebase)
dotnet_naming_rule.non_private_fields_pascal.symbols = non_private_fields
dotnet_naming_rule.non_private_fields_pascal.style = pascal_case
dotnet_naming_rule.non_private_fields_pascal.severity = suggestion

# Constants → PascalCase (suggestion)
dotnet_naming_rule.constants_pascal.symbols = constants
dotnet_naming_rule.constants_pascal.style = pascal_case
dotnet_naming_rule.constants_pascal.severity = suggestion

# Interfaces → IPascalCase (warning — agreed standard)
dotnet_naming_rule.interfaces_i_prefix.symbols = interfaces
dotnet_naming_rule.interfaces_i_prefix.style = i_prefix_pascal_case
dotnet_naming_rule.interfaces_i_prefix.severity = warning

# Type parameters → TPascalCase (suggestion)
dotnet_naming_rule.type_parameters_t_prefix.symbols = type_parameters
dotnet_naming_rule.type_parameters_t_prefix.style = t_prefix_pascal_case
dotnet_naming_rule.type_parameters_t_prefix.severity = suggestion

# Async methods → PascalCaseAsync (warning — agreed standard)
dotnet_naming_rule.async_methods_async_suffix.symbols = async_methods
dotnet_naming_rule.async_methods_async_suffix.style = pascal_case_async
dotnet_naming_rule.async_methods_async_suffix.severity = warning

# ── Structured data files ─────────────────────────────────────────────────────

[*.{json,jsn,xml,yaml,yml,props,csproj,sln,sql}]
indent_style = space
indent_size = 2
indent_size = 2

# ── Markdown ──────────────────────────────────────────────────────────────────

[*.md]
trim_trailing_whitespace = false
Loading
Loading