diff --git a/plugins/coalesce-accelerator/plugin.json b/plugins/coalesce-accelerator/plugin.json index f41b901..dd54d4b 100644 --- a/plugins/coalesce-accelerator/plugin.json +++ b/plugins/coalesce-accelerator/plugin.json @@ -21,12 +21,9 @@ "Vuetify", "TypeScript" ], - "categories": ["Framework", "FullStack"], - "contents": { - "instructions": [ - "instructions/coalesce-workflows.md", - "instructions/ef-core-patterns.md", - "instructions/code-generation.md" - ] - } + "categories": [ + "Framework", + "FullStack" + ], + "skills": "skills/" } diff --git a/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md b/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md new file mode 100644 index 0000000..00b1943 --- /dev/null +++ b/plugins/coalesce-accelerator/skills/add-data-source/SKILL.md @@ -0,0 +1,74 @@ +--- +name: add-data-source +description: Add a custom Coalesce IDataSource to filter or shape entity data for a specific use case +--- + +# Add Data Source Skill + +Create a custom Coalesce `IDataSource` implementation to provide filtered, shaped, or security-scoped access to an entity beyond the default CRUD behavior. + +## When to Use + +Invoke this skill when you need to: +- Expose a filtered subset of an entity (e.g., "only active records") +- Add includes/eager loading not present on the default source +- Scope data to the current user (tenancy, ownership) +- Return a projection or computed view of an entity + +## Data Source Pattern + +```csharp +using IntelliTect.Coalesce; +using IntelliTect.Coalesce.Api; +using IntelliTect.Coalesce.TypeDefinition; + +[Coalesce] +public class ActiveEntitySource : StandardDataSource +{ + public ActiveEntitySource(CrudContext context) : base(context) { } + + public override IQueryable GetQuery(IDataSourceParameters parameters) + => base.GetQuery(parameters) + .Where(e => e.IsActive) + .Include(e => e.RelatedEntity); +} +``` + +## Steps + +1. **Create the data source class** in a `DataSources/` folder beside your entity models +2. **Decorate with `[Coalesce]`** so the CLI picks it up during code generation +3. **Override `GetQuery`** — compose from `base.GetQuery()` to retain default filtering/sorting support +4. **Optionally override `TransformResults`** for post-query shaping +5. **Run `coalesce_generate`** to expose it in the API: + ```bash + coalesce_generate + ``` +6. **Verify the new data source appears** in the generated API and TypeScript service +7. **Write tests** that confirm filtering/scoping works correctly + +## User-Scoped Data Source Pattern + +```csharp +[Coalesce] +public class MyRecordsSource : StandardDataSource +{ + private readonly ICurrentUserService _currentUser; + + public MyRecordsSource(CrudContext context, ICurrentUserService currentUser) + : base(context) + { + _currentUser = currentUser; + } + + public override IQueryable GetQuery(IDataSourceParameters parameters) + => base.GetQuery(parameters) + .Where(r => r.OwnerId == _currentUser.UserId); +} +``` + +## Notes + +- Multiple data sources can exist for the same entity — each becomes a selectable source in the API +- The default data source is `StandardDataSource` — your custom sources supplement it +- Always test that unauthorized data cannot be reached through alternative data sources diff --git a/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md b/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md new file mode 100644 index 0000000..91aa3fc --- /dev/null +++ b/plugins/coalesce-accelerator/skills/generate-migration/SKILL.md @@ -0,0 +1,63 @@ +--- +name: generate-migration +description: Generate an EF Core migration and run it for the current Coalesce project +--- + +# Generate Migration Skill + +Generate a new EF Core database migration after making changes to Coalesce entity models, then optionally apply it to the database. + +## When to Use + +Invoke this skill after you have: +- Added, renamed, or removed a property on a Coalesce entity +- Added or removed a navigation property or relationship +- Changed a `[StringLength]`, `[Required]`, or other schema-affecting attribute +- Added a new entity class to the `DbContext` + +## Steps + +1. **Verify the model compiles** + ```bash + dotnet build + ``` + Fix any compiler errors before proceeding. + +2. **Regenerate Coalesce artifacts** to keep the API and TypeScript types in sync: + ```bash + coalesce_generate + ``` + +3. **Add the EF Core migration** using a descriptive PascalCase name that describes the change: + ```bash + dotnet ef migrations add --project --startup-project + ``` + Examples: `AddCompanyPhoneNumber`, `RemoveOrderLegacyStatus`, `AddIndexOnUserEmail` + +4. **Review the generated migration file** in `Migrations/` — verify the `Up()` and `Down()` methods match your intent. Check for: + - Unexpected table drops or column drops + - Missing `nullable` settings + - Correct foreign key constraints + +5. **Apply the migration to the database**: + ```bash + dotnet ef database update --project --startup-project + ``` + +6. **Run tests** to confirm nothing regressed: + ```bash + dotnet test + ``` + +## Naming Conventions + +Migration names should be short, PascalCase, and describe **what changed**: +- ✅ `AddUserEmailIndex` +- ✅ `RenameCompanyAddressToStreet` +- ❌ `Update1`, `Migration20240101`, `Changes` + +## Notes + +- Always review the generated `.cs` migration file before applying — EF Core may infer destructive changes +- If the migration is complex, split it: one for schema changes, one for data changes +- For seed data changes, consider a separate data migration or a custom `IHostedService` diff --git a/plugins/coalesce-accelerator/instructions/code-generation.md b/plugins/coalesce-accelerator/skills/run-code-generation/SKILL.md similarity index 96% rename from plugins/coalesce-accelerator/instructions/code-generation.md rename to plugins/coalesce-accelerator/skills/run-code-generation/SKILL.md index b14e8a9..06eee9a 100644 --- a/plugins/coalesce-accelerator/instructions/code-generation.md +++ b/plugins/coalesce-accelerator/skills/run-code-generation/SKILL.md @@ -1,3 +1,20 @@ +--- +name: run-code-generation +description: Run Coalesce code generation to regenerate TypeScript types and API client after C# model changes +--- + +# Run Code Generation Skill + +Trigger and manage Coalesce's code generation pipeline to regenerate TypeScript types, API clients, and ViewModels after C# model or service changes. + +## When to Use + +Invoke this skill when you: +- Have made changes to C# entity classes and need to regenerate TypeScript types +- Need to run coalesce_generate and understand what it produces +- Want to troubleshoot code generation errors or stale generated files +- Are setting up or configuring the code generation pipeline + # Coalesce Code Generation This guide explains what Coalesce generates, how to run code generation, customize the output, and manage regeneration workflows. diff --git a/plugins/coalesce-accelerator/instructions/ef-core-patterns.md b/plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md similarity index 87% rename from plugins/coalesce-accelerator/instructions/ef-core-patterns.md rename to plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md index 81a9456..6e72a4a 100644 --- a/plugins/coalesce-accelerator/instructions/ef-core-patterns.md +++ b/plugins/coalesce-accelerator/skills/scaffold-entity/SKILL.md @@ -1,3 +1,92 @@ +--- +name: scaffold-entity +description: Scaffold a new Coalesce entity class with EF Core annotations, navigation properties, and register it in the DbContext +--- + +# Scaffold Entity Skill + +Create a complete Coalesce-compatible C# entity class with appropriate EF Core data annotations, navigation properties, and DbContext registration. + +## When to Use + +Invoke this skill when you need to: +- Add a new domain entity to the Coalesce data model +- Create a related/child entity with a foreign key relationship +- Scaffold a lookup/reference table entity + +## Required Information + +Before scaffolding, gather: +1. **Entity name** — PascalCase noun (e.g., `Invoice`, `ProjectMilestone`) +2. **Properties** — names, types, and whether required/optional +3. **Relationships** — parent entity (if any), one-to-many or many-to-many +4. **Table name** — usually pluralized entity name (e.g., `Invoices`) + +## Scaffold Pattern + +```csharp +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using IntelliTect.Coalesce.DataAnnotations; + +[Table("EntityNamePlural")] +public class EntityName +{ + // Primary key — name must be {EntityName}Id + [Key] + public int EntityNameId { get; set; } + + // Required string property + [Required] + [StringLength(255)] + [Display(Name = "Friendly Label")] + public required string Name { get; set; } + + // Optional string property + [StringLength(1024)] + public string? Description { get; set; } + + // Foreign key + navigation (many-to-one) + public int ParentId { get; set; } + public Parent Parent { get; set; } = null!; + + // Audit fields + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime? UpdatedAt { get; set; } +} +``` + +## Steps + +1. **Create the entity file** in the `Models/` directory +2. **Add the DbSet** to the application's `DbContext`: + ```csharp + public DbSet EntityNames { get; set; } + ``` +3. **Run `coalesce_generate`** to generate the API and TypeScript types: + ```bash + coalesce_generate + ``` +4. **Create a migration** to add the table (use the `generate-migration` skill) +5. **Build and test**: + ```bash + dotnet build && dotnet test + ``` + +## Coalesce-Specific Annotations + +| Attribute | Effect | +|-----------|--------| +| `[Read(Roles = "Admin")]` | Restrict read access by role | +| `[Edit(Roles = "Admin")]` | Restrict edit access by role | +| `[Hidden]` | Exclude from generated list views | +| `[Search]` | Include property in text search | +| `[DefaultOrderBy]` | Set default sort property | +| `[ListText]` | Use as display text in dropdowns | + + +## Reference: EF Core Patterns + # Entity Framework Core Patterns with Coalesce This guide covers Entity Framework Core (EF Core) best practices, patterns, and configurations specifically for Coalesce development. diff --git a/plugins/coalesce-accelerator/instructions/coalesce-workflows.md b/plugins/coalesce-accelerator/skills/setup-coalesce-project/SKILL.md similarity index 95% rename from plugins/coalesce-accelerator/instructions/coalesce-workflows.md rename to plugins/coalesce-accelerator/skills/setup-coalesce-project/SKILL.md index 15762d2..26063af 100644 --- a/plugins/coalesce-accelerator/instructions/coalesce-workflows.md +++ b/plugins/coalesce-accelerator/skills/setup-coalesce-project/SKILL.md @@ -1,3 +1,20 @@ +--- +name: setup-coalesce-project +description: Set up a new Coalesce full-stack project from scratch including models, DbContext, and project structure +--- + +# Setup Coalesce Project Skill + +Guide the full setup of a new Coalesce full-stack project including C# models, EF Core DbContext, Coalesce configuration, and Vue 3 frontend scaffolding. + +## When to Use + +Invoke this skill when you: +- Are starting a brand new Coalesce project from scratch +- Need to configure an existing project to use Coalesce +- Want to understand the required project structure and dependencies +- Are setting up the full development workflow for a Coalesce application + # Coalesce Workflows This guide covers the end-to-end workflows for developing with Coalesce, from project setup through code generation to full-stack deployment. diff --git a/plugins/csharp-best-practices/plugin.json b/plugins/csharp-best-practices/plugin.json index 4e76b0e..4e57997 100644 --- a/plugins/csharp-best-practices/plugin.json +++ b/plugins/csharp-best-practices/plugin.json @@ -22,12 +22,9 @@ "enterprise", "dotnet" ], - "categories": ["Language", "Enterprise"], - "contents": { - "instructions": [ - "instructions/csharp-patterns.md", - "instructions/naming-conventions.md", - "instructions/async-patterns.md" - ] - } + "categories": [ + "Language", + "Enterprise" + ], + "skills": "skills/" } diff --git a/plugins/csharp-best-practices/instructions/csharp-patterns.md b/plugins/csharp-best-practices/skills/apply-csharp-patterns/SKILL.md similarity index 96% rename from plugins/csharp-best-practices/instructions/csharp-patterns.md rename to plugins/csharp-best-practices/skills/apply-csharp-patterns/SKILL.md index 97adc5f..57ee358 100644 --- a/plugins/csharp-best-practices/instructions/csharp-patterns.md +++ b/plugins/csharp-best-practices/skills/apply-csharp-patterns/SKILL.md @@ -1,3 +1,20 @@ +--- +name: apply-csharp-patterns +description: Apply enterprise C# patterns including error handling, dependency injection, and clean code principles +--- + +# Apply C# Patterns Skill + +Apply idiomatic C# language patterns including type design, null handling, pattern matching, LINQ, and modern C# features for clean, maintainable enterprise code. + +## When to Use + +Invoke this skill when you: +- Need to refactor existing code to follow C# best practices +- Are writing new C# code and want to apply proper patterns +- Want a review of C# language feature usage in a file or class +- Are modernizing older C# code to use current language features + # C# Language Patterns & Best Practices Comprehensive guide to idiomatic C# patterns, type design, and language features for writing maintainable, performant code. diff --git a/plugins/csharp-best-practices/instructions/naming-conventions.md b/plugins/csharp-best-practices/skills/check-naming/SKILL.md similarity index 87% rename from plugins/csharp-best-practices/instructions/naming-conventions.md rename to plugins/csharp-best-practices/skills/check-naming/SKILL.md index 4ea4c8d..0f37f9f 100644 --- a/plugins/csharp-best-practices/instructions/naming-conventions.md +++ b/plugins/csharp-best-practices/skills/check-naming/SKILL.md @@ -1,3 +1,99 @@ +--- +name: check-naming +description: Check C# naming conventions in a file or selection against Microsoft and project standards +--- + +# Check Naming Skill + +Audit C# identifiers in the current file or selection for adherence to Microsoft naming conventions and enterprise project standards. + +## When to Use + +Invoke this skill when you: +- Want to validate naming before committing or opening a pull request +- Are reviewing code from someone unfamiliar with C# conventions +- Migrated code from another language and need a naming pass +- Want to enforce consistent style across a new file + +## Conventions Checked + +### Types (classes, interfaces, records, structs, enums) +```csharp +// ✅ PascalCase +public class UserAccountService { } +public interface IEmailSender { } +public record OrderSummary(int Id, decimal Total); +public enum OrderStatus { Pending, Active, Closed } + +// ❌ +public class userAccountService { } // camelCase +public interface EmailSender { } // missing I prefix +``` + +### Methods and properties +```csharp +// ✅ PascalCase +public string GetDisplayName() { } +public bool IsActive { get; set; } +public async Task GetUserAsync(int id) { } // Async suffix + +// ❌ +public string getDisplayName() { } // camelCase +public async Task GetUser(int id) { } // missing Async suffix +``` + +### Private fields +```csharp +// ✅ _camelCase with underscore prefix +private readonly ILogger _logger; +private string _cachedValue; + +// ❌ +private readonly ILogger logger; // no underscore +private string CachedValue; // PascalCase for field +``` + +### Constants and static readonly +```csharp +// ✅ PascalCase +public const int MaxRetryCount = 3; +private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); + +// ❌ +public const int MAX_RETRY_COUNT = 3; // SCREAMING_CASE +``` + +### Parameters and local variables +```csharp +// ✅ camelCase +public void Process(int userId, string displayName) { } +var orderCount = orders.Count(); + +// ❌ +public void Process(int UserId, string DisplayName) { } // PascalCase +``` + +### Generic type parameters +```csharp +// ✅ T, or TKey/TValue for multiple parameters +public class Repository where T : class { } +public class Dictionary { } + +// ❌ +public class Repository { } // descriptive word without T prefix +``` + +## Review Output + +For each violation found, report: +- **Identifier**: the name that violates the convention +- **Expected convention**: what it should be +- **Suggested name**: the corrected identifier +- **Location**: line number in the file + + +## Reference: Naming Conventions + # C# Naming Conventions & Code Organization Professional naming conventions aligned with Microsoft guidelines and industry best practices. diff --git a/plugins/csharp-best-practices/instructions/async-patterns.md b/plugins/csharp-best-practices/skills/review-async/SKILL.md similarity index 90% rename from plugins/csharp-best-practices/instructions/async-patterns.md rename to plugins/csharp-best-practices/skills/review-async/SKILL.md index affa3d9..713c66f 100644 --- a/plugins/csharp-best-practices/instructions/async-patterns.md +++ b/plugins/csharp-best-practices/skills/review-async/SKILL.md @@ -1,3 +1,91 @@ +--- +name: review-async +description: Review async/await usage in a C# file or selection for common pitfalls and anti-patterns +--- + +# Review Async Skill + +Audit async/await usage in the current file or selected code for correctness, safety, and adherence to C# async best practices. + +## When to Use + +Invoke this skill when you: +- Want to check a file for async anti-patterns before code review +- Suspect a deadlock or performance issue caused by improper async usage +- Are migrating synchronous code to async and want a validation pass +- Added new async methods and want them reviewed + +## What This Skill Checks + +### 1. Blocking on async (deadlock risk) +```csharp +// ❌ Dangerous — can deadlock in non-console contexts +var result = GetDataAsync().Result; +var result = GetDataAsync().GetAwaiter().GetResult(); +Task.Run(() => GetDataAsync()).Wait(); + +// ✅ Correct +var result = await GetDataAsync(); +``` + +### 2. async void (fire-and-forget danger) +```csharp +// ❌ Exceptions are unobservable +public async void LoadData() { ... } + +// ✅ Use Task return type; async void only for event handlers +public async Task LoadDataAsync() { ... } +``` + +### 3. Missing ConfigureAwait(false) in library code +```csharp +// ❌ In a library — may cause deadlocks in UI/ASP.NET contexts +await _client.GetAsync(url); + +// ✅ In library code +await _client.GetAsync(url).ConfigureAwait(false); +``` + +### 4. Unnecessary async wrapper +```csharp +// ❌ Unnecessary state machine overhead +public async Task GetCountAsync() => await _repo.CountAsync(); + +// ✅ Just return the Task directly +public Task GetCountAsync() => _repo.CountAsync(); +``` + +### 5. Missing CancellationToken propagation +```csharp +// ❌ Ignores cancellation +public async Task ProcessAsync() { await _db.SaveChangesAsync(); } + +// ✅ Propagates cancellation +public async Task ProcessAsync(CancellationToken ct = default) + { await _db.SaveChangesAsync(ct); } +``` + +### 6. Unobserved task (fire-and-forget without handling) +```csharp +// ❌ Exception is swallowed +_ = DoWorkAsync(); + +// ✅ If fire-and-forget is intentional, handle exceptions +_ = DoWorkAsync().ContinueWith(t => _logger.LogError(t.Exception, "Background task failed"), + TaskContinuationOptions.OnlyOnFaulted); +``` + +## Review Output + +For each issue found, report: +- **Location**: file name and line number +- **Issue type**: one of the categories above +- **Severity**: Warning or Error +- **Suggested fix**: corrected code snippet + + +## Reference: Async Patterns + # C# Async/Await Best Practices Comprehensive guide to asynchronous programming in C# using async/await, Tasks, and cancellation patterns. diff --git a/plugins/enterprise-bug-fixing/.mcp.json b/plugins/enterprise-bug-fixing/.mcp.json new file mode 100644 index 0000000..5ec6a3f --- /dev/null +++ b/plugins/enterprise-bug-fixing/.mcp.json @@ -0,0 +1,32 @@ +{ + "mcpServers": { + "ado_with_filtered_domains": { + "description": "Azure DevOps MCP server for querying work items, boards, and pipelines. Required for work item retrieval in the bug-fix workflow.", + "notes": "Install from: https://github.com/microsoft/azure-devops-mcp — configure ADO_ORGANIZATION and ADO_PAT environment variables before use.", + "command": "npx", + "args": ["-y", "@microsoft/azure-devops-mcp"], + "env": { + "ADO_ORGANIZATION": "${ADO_ORGANIZATION}", + "ADO_PAT": "${ADO_PAT}" + } + }, + "context7": { + "description": "Context7 MCP server for accessing up-to-date library documentation (Coalesce, ASP.NET Core, EF Core). Used by the bug-fix agent to look up API references.", + "notes": "Install from: https://github.com/upstash/context7-mcp", + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"] + }, + "nuget": { + "description": "NuGet MCP server for querying package versions and vulnerability information during bug analysis.", + "notes": "Install from: https://github.com/github/github-mcp-server or equivalent NuGet MCP integration.", + "command": "npx", + "args": ["-y", "@microsoft/nuget-mcp"] + }, + "playwright": { + "description": "Playwright MCP server for browser-based testing and end-to-end validation during bug fixing.", + "notes": "Install from: https://github.com/microsoft/playwright-mcp — requires Node.js and Playwright browsers.", + "command": "npx", + "args": ["-y", "@playwright/mcp@latest"] + } + } +} diff --git a/plugins/enterprise-bug-fixing/plugin.json b/plugins/enterprise-bug-fixing/plugin.json index df49b04..742415c 100644 --- a/plugins/enterprise-bug-fixing/plugin.json +++ b/plugins/enterprise-bug-fixing/plugin.json @@ -21,9 +21,11 @@ "root-cause-analysis", "validation" ], - "categories": ["Specialized", "Workflow"], - "contents": { - "agents": ["agents/BugFixerAgent.agent.md"], - "instructions": ["instructions/bug-fixing-workflow.md"] - } + "categories": [ + "Specialized", + "Workflow" + ], + "agents": "agents/", + "skills": "skills/", + "mcpServers": ".mcp.json" } diff --git a/plugins/enterprise-bug-fixing/instructions/bug-fixing-workflow.md b/plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md similarity index 92% rename from plugins/enterprise-bug-fixing/instructions/bug-fixing-workflow.md rename to plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md index 20f0c2c..c7b7ae0 100644 --- a/plugins/enterprise-bug-fixing/instructions/bug-fixing-workflow.md +++ b/plugins/enterprise-bug-fixing/skills/start-bug-fix/SKILL.md @@ -1,3 +1,65 @@ +--- +name: start-bug-fix +description: Kick off the full enterprise bug-fix workflow — retrieve a work item from Azure DevOps and begin the structured fix process +--- + +# Start Bug Fix Skill + +Launch the structured enterprise bug-fix workflow for an Azure DevOps work item. This skill delegates to the BugFixerAgent to drive the full process from work item retrieval through to a code-review-ready branch. + +## When to Use + +Invoke this skill when you: +- Have an Azure DevOps bug or PBI number and want to begin fixing it +- Need to start a test-first bug-fix workflow +- Want the full structured process (branch creation, test writing, fix, validation) + +## Usage + +Provide the Azure DevOps work item number when invoking: + +``` +/skills invoke start-bug-fix +``` + +You will be prompted for the work item number if not already provided. + +## What This Skill Does + +This skill activates the **BugFixerAgent** and begins the following workflow: + +``` +1. Retrieve work item from Azure DevOps +2. Analyze and understand root cause +3. Create feature branch (format: {initials}/pbi{number}) +4. Write tests that reproduce the bug (test-first) +5. Implement the minimal fix +6. Validate: run tests, build, check for regressions +7. Handle model/Coalesce changes if applicable +8. Pre-completion checklist +9. Mark as ready for code review +``` + +## Inputs Required + +- **Work item number** — e.g., `12345` or `PBI 12345` +- **Project** (optional) — defaults to `CMA` if not specified + +## Branch Naming Convention + +Feature branches are named: `{user_initials}/pbi{work_item_number}` + +Examples: `kb/pbi12345`, `jd/pbi67890` + +## Notes + +- Do not start this skill without a valid work item number — the agent will ask for one +- If you are already on a feature branch, the agent will ask whether to continue on it or create a new one +- Tests must fail before the fix and pass after — this is enforced by the workflow + + +## Reference: Bug-Fix Workflow + # Enterprise Bug Fixing Workflow A comprehensive guide to systematic bug fixing using test-first methodology, root cause analysis, and enterprise-grade validation. diff --git a/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md b/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md new file mode 100644 index 0000000..e9b0e43 --- /dev/null +++ b/plugins/enterprise-bug-fixing/skills/write-bug-tests/SKILL.md @@ -0,0 +1,71 @@ +--- +name: write-bug-tests +description: Write xUnit tests that reproduce a specific bug before the fix is implemented (test-first approach) +--- + +# Write Bug Tests Skill + +Write failing xUnit tests that precisely reproduce a bug's behavior, following the test-first methodology. Tests should fail before the fix and pass after it. + +## When to Use + +Invoke this skill when you: +- Have identified the root cause of a bug and need to write tests before fixing it +- Want to ensure the fix doesn't regress later +- Need to document the expected behavior through tests + +## Inputs Required + +- Description of the bug (what happens vs. what should happen) +- The class/method where the bug occurs +- Any known reproduction steps + +## Test Structure + +Each bug-reproduction test must follow Arrange-Act-Assert: + +```csharp +[Fact] +public void ClassName_WhenBugCondition_ShouldExpectedBehavior() +{ + // Arrange — set up the bug-triggering scenario + var sut = new ServiceUnderTest(); + var input = CreateBugTriggeringInput(); + + // Act — perform the action that triggers the bug + var result = sut.MethodUnderTest(input); + + // Assert — verify the CORRECT (post-fix) behavior + Assert.Equal(expectedValue, result); +} +``` + +## Test Naming Convention + +Name tests to describe the business scenario, not the implementation: + +- ✅ `Order_WhenCancelledAfterShipment_ShouldNotRefundCustomer` +- ✅ `Invoice_WhenTaxRateIsZero_ShouldNotThrowException` +- ❌ `TestMethod1`, `FixBug123`, `CheckNull` + +## Steps + +1. **Identify the affected class and method** +2. **Locate or create the test file** — follow existing test project naming conventions +3. **Write a test that reproduces the bug** — it must fail with the current code +4. **Run the test to confirm it fails**: + ```bash + dotnet test --filter "FullyQualifiedName~TestClassName" + ``` +5. **Write additional tests** for: + - The happy path (normal behavior) + - Edge cases mentioned in the work item + - Related scenarios that could regress + +## Guidelines + +- Test business requirements, not implementation details +- Use realistic test data (not `"test"`, `0`, or `null` unless that's the bug trigger) +- Each test verifies exactly one business requirement +- Avoid complex test logic — if the test is hard to read, simplify it +- Do not use `Assert.True(result != null)` — use `Assert.NotNull(result)` diff --git a/plugins/solid-principles/plugin.json b/plugins/solid-principles/plugin.json index d1797ef..7bbe58a 100644 --- a/plugins/solid-principles/plugin.json +++ b/plugins/solid-principles/plugin.json @@ -22,8 +22,10 @@ "C#", "dotnet" ], - "categories": ["Enterprise", "Architecture", "Code Quality"], - "contents": { - "instructions": ["instructions/solid-architecture.md"] - } + "categories": [ + "Enterprise", + "Architecture", + "Code Quality" + ], + "skills": "skills/" } diff --git a/plugins/solid-principles/instructions/solid-architecture.md b/plugins/solid-principles/skills/apply-solid/SKILL.md similarity index 98% rename from plugins/solid-principles/instructions/solid-architecture.md rename to plugins/solid-principles/skills/apply-solid/SKILL.md index 71fc6bc..807460c 100644 --- a/plugins/solid-principles/instructions/solid-architecture.md +++ b/plugins/solid-principles/skills/apply-solid/SKILL.md @@ -1,3 +1,20 @@ +--- +name: apply-solid +description: Apply SOLID principles to C# code including SRP, OCP, LSP, ISP, and DIP +--- + +# Apply SOLID Principles Skill + +Apply SOLID architecture principles to C# codebases to improve maintainability, testability, and extensibility. + +## When to Use + +Invoke this skill when you: +- Need to review code for SOLID principle violations +- Are refactoring a class or module to improve separation of concerns +- Want to apply dependency inversion to decouple components +- Are designing new classes and want to follow SOLID from the start + --- description: "Enterprise-grade guidance on SOLID principles, architecture patterns, and code quality for maintainable C# projects." applyTo: "**/*.cs" diff --git a/plugins/testing-essentials/plugin.json b/plugins/testing-essentials/plugin.json index ba9bc9a..3487275 100644 --- a/plugins/testing-essentials/plugin.json +++ b/plugins/testing-essentials/plugin.json @@ -19,11 +19,9 @@ "xUnit", "mocking" ], - "categories": ["Enterprise", "Testing"], - "contents": { - "instructions": [ - "instructions/testing-best-practices.md", - "instructions/unit-testing-patterns.md" - ] - } + "categories": [ + "Enterprise", + "Testing" + ], + "skills": "skills/" } diff --git a/plugins/testing-essentials/instructions/unit-testing-patterns.md b/plugins/testing-essentials/skills/apply-testing-patterns/SKILL.md similarity index 96% rename from plugins/testing-essentials/instructions/unit-testing-patterns.md rename to plugins/testing-essentials/skills/apply-testing-patterns/SKILL.md index 6382515..80d5998 100644 --- a/plugins/testing-essentials/instructions/unit-testing-patterns.md +++ b/plugins/testing-essentials/skills/apply-testing-patterns/SKILL.md @@ -1,3 +1,20 @@ +--- +name: apply-testing-patterns +description: Apply enterprise unit testing patterns including test doubles, data-driven tests, and test organization +--- + +# Apply Testing Patterns Skill + +Apply advanced unit testing patterns including test doubles (mocks, stubs, fakes), data-driven tests, test organization strategies, and enterprise testing conventions. + +## When to Use + +Invoke this skill when you: +- Need to implement complex test scenarios with multiple test doubles +- Want to apply data-driven or theory-based test patterns +- Are organizing a test suite and need structural guidance +- Need to test edge cases with parameterized test data + # Unit Testing Patterns Advanced patterns and strategies for comprehensive test coverage in enterprise C# applications. diff --git a/plugins/testing-essentials/instructions/testing-best-practices.md b/plugins/testing-essentials/skills/write-unit-tests/SKILL.md similarity index 81% rename from plugins/testing-essentials/instructions/testing-best-practices.md rename to plugins/testing-essentials/skills/write-unit-tests/SKILL.md index 8226010..bcb8fb1 100644 --- a/plugins/testing-essentials/instructions/testing-best-practices.md +++ b/plugins/testing-essentials/skills/write-unit-tests/SKILL.md @@ -1,3 +1,118 @@ +--- +name: write-unit-tests +description: Write xUnit unit tests for a C# class or method following Arrange-Act-Assert and enterprise testing patterns +--- + +# Write Unit Tests Skill + +Generate comprehensive xUnit unit tests for a specified C# class or method, covering the happy path, error conditions, boundary values, and edge cases. + +## When to Use + +Invoke this skill when you: +- Need to add tests to an existing untested class or method +- Are practicing TDD and want to write tests before implementation +- Want comprehensive coverage before a refactor +- Are reviewing a PR and need to add missing test cases + +## Required Information + +Provide: +1. **Class and method to test** — e.g., `OrderService.PlaceOrder` +2. **What it does** — brief description of the behavior +3. **Key scenarios** — happy path, failure cases, edge cases you want covered + +## Test File Structure + +```csharp +using FluentAssertions; +using Moq; +using Xunit; + +namespace MyApp.Tests.Services; + +public class OrderServiceTests +{ + // Shared mocks/fixtures + private readonly Mock _repositoryMock = new(); + private readonly Mock _emailMock = new(); + private OrderService CreateSut() => + new(_repositoryMock.Object, _emailMock.Object); + + [Fact] + public async Task PlaceOrder_WithValidInput_CreatesOrderAndSendsConfirmation() + { + // Arrange + var order = new Order { CustomerId = 1, Items = [new OrderItem { ProductId = 5, Qty = 2 }] }; + _repositoryMock.Setup(r => r.SaveAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(order with { OrderId = 42 }); + var sut = CreateSut(); + + // Act + var result = await sut.PlaceOrderAsync(order); + + // Assert + result.OrderId.Should().Be(42); + _emailMock.Verify(e => e.SendConfirmationAsync(order.CustomerId, 42, It.IsAny()), Times.Once); + } + + [Fact] + public async Task PlaceOrder_WithEmptyItems_ThrowsValidationException() + { + // Arrange + var order = new Order { CustomerId = 1, Items = [] }; + var sut = CreateSut(); + + // Act + var act = () => sut.PlaceOrderAsync(order); + + // Assert + await act.Should().ThrowAsync() + .WithMessage("*at least one item*"); + } +} +``` + +## Test Categories to Cover + +For each method, generate tests for: + +| Category | Description | +|----------|-------------| +| **Happy path** | Valid input, expected output | +| **Null / empty input** | `null`, empty string, empty collection | +| **Boundary values** | Min/max values, limits | +| **Invalid state** | Precondition failures | +| **Exception handling** | What throws and what is caught | +| **Dependency interactions** | Verify mocks called correctly | + +## Test Naming Convention + +``` +MethodName_WhenCondition_ExpectedOutcome +``` + +Examples: +- `PlaceOrder_WithValidInput_CreatesOrderAndSendsConfirmation` +- `GetUser_WhenUserNotFound_ReturnsNull` +- `ProcessPayment_WhenAmountExceedsLimit_ThrowsException` + +## Mocking Guidelines + +- Use `Moq` for interface mocks +- Prefer `Mock.Setup(...).ReturnsAsync(...)` over `.Returns(Task.FromResult(...))` +- Verify interactions with `.Verify(...)` only when the call itself is the behavior under test +- Use `It.IsAny()` for parameters you don't care about; use specific values when the value matters + +## Assertions + +- Use `FluentAssertions` (`.Should().Be(...)`, `.Should().Contain(...)`) for readable assertions +- One logical assertion per test — multiple `.Should()` calls on the same object are fine +- For exceptions: use `act.Should().ThrowAsync()` instead of `Assert.ThrowsAsync` + + +## Reference: Testing Best Practices + # Testing Best Practices This guide covers the fundamental philosophy and patterns for writing sustainable unit tests in enterprise C# applications. diff --git a/plugins/vuetify-components/plugin.json b/plugins/vuetify-components/plugin.json index db5bf08..62a85f0 100644 --- a/plugins/vuetify-components/plugin.json +++ b/plugins/vuetify-components/plugin.json @@ -22,12 +22,11 @@ "responsive-design", "composition-api" ], - "categories": ["Framework", "Frontend", "UI/UX", "Accessibility"], - "contents": { - "instructions": [ - "instructions/vuetify-components.md", - "instructions/vue3-composition.md", - "instructions/accessibility-ux.md" - ] - } + "categories": [ + "Framework", + "Frontend", + "UI/UX", + "Accessibility" + ], + "skills": "skills/" } diff --git a/plugins/vuetify-components/instructions/accessibility-ux.md b/plugins/vuetify-components/skills/add-accessibility/SKILL.md similarity index 97% rename from plugins/vuetify-components/instructions/accessibility-ux.md rename to plugins/vuetify-components/skills/add-accessibility/SKILL.md index 3364cff..8cac523 100644 --- a/plugins/vuetify-components/instructions/accessibility-ux.md +++ b/plugins/vuetify-components/skills/add-accessibility/SKILL.md @@ -1,3 +1,20 @@ +--- +name: add-accessibility +description: Add WCAG-compliant accessibility and UX improvements to Vuetify components +--- + +# Add Accessibility Skill + +Audit and improve Vuetify Vue 3 components for WCAG compliance, keyboard navigation, ARIA labeling, color contrast, and overall UX quality. + +## When to Use + +Invoke this skill when you: +- Need to audit a component for accessibility issues +- Are adding ARIA labels, roles, or keyboard navigation support +- Want to ensure color contrast and visual accessibility standards +- Need to improve UX consistency and Vuetify component usage + # Accessibility & UX Best Practices Build inclusive, professional user interfaces that work for everyone. Master WCAG accessibility standards, semantic HTML, keyboard navigation, and accessibility testing. diff --git a/plugins/vuetify-components/skills/add-form/SKILL.md b/plugins/vuetify-components/skills/add-form/SKILL.md new file mode 100644 index 0000000..b5e06e1 --- /dev/null +++ b/plugins/vuetify-components/skills/add-form/SKILL.md @@ -0,0 +1,113 @@ +--- +name: add-form +description: Add a Vuetify form with validation to a Vue 3 component using VeeValidate or Vuetify's built-in validation +--- + +# Add Form Skill + +Add a validated Vuetify form to an existing or new Vue 3 component, including field definitions, validation rules, submission handling, and error display. + +## When to Use + +Invoke this skill when you need to: +- Add a create/edit form for a domain entity +- Add a search or filter form +- Add a settings or preferences form with validation +- Convert an unvalidated form to one with proper error handling + +## Required Information + +Provide: +1. **Fields** — names, types (`text`, `number`, `date`, `select`, `checkbox`), and validation rules +2. **Submit action** — what happens on successful submission (API call, event emit, navigation) +3. **Validation approach** — Vuetify built-in rules or VeeValidate + +## Vuetify Built-In Validation Pattern + +```vue + + + +``` + +## Validation Rules Reference + +| Rule | Pattern | +|------|---------| +| Required | `v => !!v \|\| 'Required'` | +| Min length | `v => v.length >= n \|\| 'Min n chars'` | +| Max length | `v => v.length <= n \|\| 'Max n chars'` | +| Email | `v => /.+@.+\..+/.test(v) \|\| 'Invalid email'` | +| Numeric range | `v => (v >= min && v <= max) \|\| 'Out of range'` | + +## UX Guidelines + +- Show validation errors only after the user has interacted with a field (`validate-on="blur"`) +- Disable the submit button only while submitting (`loading` prop), not while the form is invalid +- Display a top-level error alert for server-side errors +- Reset the form on cancel with `form.value?.reset()` +- Use `v-btn type="submit"` to enable native form submission (Enter key support) diff --git a/plugins/vuetify-components/instructions/vuetify-components.md b/plugins/vuetify-components/skills/scaffold-component/SKILL.md similarity index 93% rename from plugins/vuetify-components/instructions/vuetify-components.md rename to plugins/vuetify-components/skills/scaffold-component/SKILL.md index 5414e90..bd3c084 100644 --- a/plugins/vuetify-components/instructions/vuetify-components.md +++ b/plugins/vuetify-components/skills/scaffold-component/SKILL.md @@ -1,3 +1,97 @@ +--- +name: scaffold-component +description: Scaffold a new Vuetify Vue 3 component using the Composition API with proper structure, props, emits, and accessibility +--- + +# Scaffold Component Skill + +Generate a well-structured Vuetify Vue 3 single-file component (SFC) using the Composition API, following accessibility and UX best practices. + +## When to Use + +Invoke this skill when you need to: +- Create a new reusable UI component +- Add a page-level component that wraps Vuetify layout components +- Build a data display component (table, card, list) +- Create a modal or dialog component + +## Required Information + +Before scaffolding, provide: +1. **Component name** — PascalCase (e.g., `UserCard`, `InvoiceTable`, `ConfirmDialog`) +2. **Component purpose** — what data it displays or action it performs +3. **Props** — inputs from parent (names, types, whether required) +4. **Emits** — events the component raises to parent (e.g., `update:modelValue`, `confirm`) + +## SFC Structure + +```vue + + + +``` + +## Accessibility Requirements + +- Always use semantic Vuetify components (`v-btn` over `div` for buttons) +- Provide `aria-label` on icon-only buttons: + ```html + + ``` +- Use `v-tooltip` to add tooltips for icon actions +- Ensure keyboard navigation works (Vuetify handles most of this automatically) +- Color alone must not convey meaning — pair with text or icon + +## File Placement + +Place the component in the appropriate directory: +- Reusable components → `src/components/` +- Page-level components → `src/views/` +- Domain-specific components → `src/components/{domain}/` + +## Notes + +- Use `