@polymorphism-tech/morph-spec 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +314 -1673
- package/LICENSE +72 -72
- package/README.md +515 -516
- package/bin/detect-agents.js +225 -225
- package/bin/morph-spec.js +358 -173
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/task-manager.js +429 -0
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/bin/validate.js +369 -0
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/checklists/code-review.md +226 -0
- package/content/.claude/skills/checklists/morph-checklist.md +117 -0
- package/content/.claude/skills/checklists/simulation-checklist.md +77 -0
- package/content/.claude/skills/infra/bicep-architect.md +126 -419
- package/content/.claude/skills/infra/container-specialist.md +131 -437
- package/content/.claude/skills/infra/devops-engineer.md +119 -405
- package/content/.claude/skills/integrations/asaas-financial.md +130 -333
- package/content/.claude/skills/integrations/azure-identity.md +142 -309
- package/content/.claude/skills/integrations/clerk-auth.md +108 -290
- package/content/.claude/skills/integrations/resend-email.md +119 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +192 -604
- package/content/.claude/skills/specialists/azure-architect.md +142 -142
- package/content/.claude/skills/specialists/code-analyzer.md +235 -0
- package/content/.claude/skills/specialists/dotnet-senior.md +287 -0
- package/content/.claude/skills/specialists/ef-modeler.md +113 -200
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +126 -245
- package/content/.claude/skills/specialists/ms-agent-expert.md +109 -263
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -197
- package/content/.claude/skills/specialists/standards-architect.md +156 -78
- package/content/.claude/skills/specialists/testing-specialist.md +126 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +191 -1060
- package/content/.claude/skills/stacks/dotnet-blazor.md +210 -588
- package/content/.claude/skills/stacks/dotnet-nextjs.md +154 -402
- package/content/.claude/skills/workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/workflows/phase-clarify.md} +5 -58
- package/content/.claude/{commands/morph-design.md → skills/workflows/phase-design.md} +16 -86
- package/content/.claude/{commands/morph-setup.md → skills/workflows/phase-setup.md} +9 -17
- package/content/.claude/skills/workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/workflows/phase-uiux.md} +15 -88
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +378 -242
- package/content/.morph/config/config.template.json +89 -108
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/examples/state-v3.json +188 -0
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/README.md +190 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/CLAUDE.md +150 -442
- package/content/README.md +79 -79
- package/detectors/config-detector.js +223 -223
- package/detectors/conversation-analyzer.js +163 -163
- package/detectors/index.js +84 -84
- package/detectors/standards-generator.js +275 -275
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/templates.md +418 -418
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/scripts/postinstall.js +132 -132
- package/src/commands/advance-phase.js +183 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/create-story.js +351 -351
- package/src/commands/detect-agents.js +139 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate.js +149 -149
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +333 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/task.js +78 -0
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/continuous-validator.js +421 -0
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/learning-system.js +520 -0
- package/src/lib/mockup-generator.js +366 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/ui-detector.js +350 -0
- package/src/lib/validation-runner.js +231 -0
- package/src/lib/validators/architecture-validator.js +387 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/package-validator.js +360 -0
- package/src/lib/validators/ui-contrast-validator.js +422 -0
- package/src/utils/file-copier.js +179 -139
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# .NET Senior Engineer
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** always | **Scope:** All .NET projects (Core Agent)
|
|
4
|
+
|
|
5
|
+
Senior .NET engineer specialist. Writes production-quality C# following all framework standards. Includes **Ultrathink Mode** for complex architectural decisions.
|
|
6
|
+
|
|
7
|
+
> **Ref:** `framework/standards/coding.md` — ALL code output MUST follow these conventions.
|
|
8
|
+
> **Ref:** `framework/standards/architecture.md` — ALL code MUST respect layer boundaries.
|
|
9
|
+
> **Ref:** `.claude/skills/checklists/code-review.md` — Self-check before delivering code.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Two Modes
|
|
14
|
+
|
|
15
|
+
### Standard Mode (default)
|
|
16
|
+
|
|
17
|
+
Active for all C# code writing. Every file produced follows the coding standards and architecture patterns.
|
|
18
|
+
|
|
19
|
+
**Trigger:** Any implementation task (always active as Core Agent).
|
|
20
|
+
|
|
21
|
+
### Ultrathink Mode
|
|
22
|
+
|
|
23
|
+
Extended deep-reasoning mode for complex decisions. Think step by step through trade-offs before recommending.
|
|
24
|
+
|
|
25
|
+
**Trigger keywords:** `ultrathink`, `deep-think`, `think deeply`, `analyze deeply`, `complex decision`
|
|
26
|
+
|
|
27
|
+
**Use for:**
|
|
28
|
+
- Technology/library selection (MudBlazor vs Fluent UI, Hangfire vs Azure Functions)
|
|
29
|
+
- Architecture pattern decisions (CQRS vs simple, Repository vs direct DbContext)
|
|
30
|
+
- Performance optimization strategy
|
|
31
|
+
- Migration planning (.NET version upgrades, library migrations)
|
|
32
|
+
- Multi-system integration design
|
|
33
|
+
- Database schema design for complex domains
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Code Writing Rules
|
|
38
|
+
|
|
39
|
+
**MANDATORY for ALL C# code output.** No exceptions.
|
|
40
|
+
|
|
41
|
+
### Naming (ref: coding.md)
|
|
42
|
+
|
|
43
|
+
| Element | Convention | Example |
|
|
44
|
+
|---------|-----------|---------|
|
|
45
|
+
| Classes | PascalCase + `sealed` | `public sealed class OrderService` |
|
|
46
|
+
| Interfaces | `I` + PascalCase | `public interface IOrderService` |
|
|
47
|
+
| Methods | PascalCase + `Async` | `public async Task<Result<Order>> GetByIdAsync(...)` |
|
|
48
|
+
| Constants | PascalCase | `private const int MaxRetryCount = 3;` |
|
|
49
|
+
| Private fields | `_camelCase` | `private readonly ILogger<OrderService> _logger;` |
|
|
50
|
+
| Parameters | camelCase | `(int orderId, CancellationToken ct = default)` |
|
|
51
|
+
|
|
52
|
+
### Structure
|
|
53
|
+
|
|
54
|
+
```csharp
|
|
55
|
+
// 1. File-scoped namespace
|
|
56
|
+
namespace MyApp.Application.Services;
|
|
57
|
+
|
|
58
|
+
// 2. Primary constructor for DI (preferred) or traditional constructor
|
|
59
|
+
public sealed class OrderService(
|
|
60
|
+
IOrderRepository repository,
|
|
61
|
+
IPaymentGateway paymentGateway,
|
|
62
|
+
ILogger<OrderService> logger) : IOrderService
|
|
63
|
+
{
|
|
64
|
+
// 3. Constants first (PascalCase)
|
|
65
|
+
private const int MaxRetryCount = 3;
|
|
66
|
+
private const string DefaultCurrency = "BRL";
|
|
67
|
+
|
|
68
|
+
// 4. Public methods (business operations)
|
|
69
|
+
public async Task<Result<OrderResponse>> CreateAsync(
|
|
70
|
+
CreateOrderRequest request,
|
|
71
|
+
CancellationToken ct = default)
|
|
72
|
+
{
|
|
73
|
+
// 5. Entry logging with correlation
|
|
74
|
+
logger.LogInformation("Creating order for customer {CustomerId}", request.CustomerId);
|
|
75
|
+
|
|
76
|
+
// 6. Validation (early return with Result)
|
|
77
|
+
if (request.Items.Count == 0)
|
|
78
|
+
return Result.Failure<OrderResponse>("Order must have at least one item");
|
|
79
|
+
|
|
80
|
+
// 7. Domain logic
|
|
81
|
+
var order = Order.Create(request.CustomerId, request.Items);
|
|
82
|
+
|
|
83
|
+
// 8. Persistence
|
|
84
|
+
await repository.AddAsync(order, ct);
|
|
85
|
+
await repository.SaveChangesAsync(ct);
|
|
86
|
+
|
|
87
|
+
// 9. Exit logging
|
|
88
|
+
logger.LogInformation("Order {OrderId} created successfully", order.Id);
|
|
89
|
+
|
|
90
|
+
// 10. Return mapped response
|
|
91
|
+
return Result.Success(order.ToResponse());
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Mandatory Patterns
|
|
97
|
+
|
|
98
|
+
| Pattern | Rule | Example |
|
|
99
|
+
|---------|------|---------|
|
|
100
|
+
| **CancellationToken** | Last parameter on ALL async methods | `CancellationToken ct = default` |
|
|
101
|
+
| **Result pattern** | Business errors return Result, NOT exceptions | `Result.Failure<T>("message")` |
|
|
102
|
+
| **Structured logging** | Entry + exit + error on every service method | `logger.LogInformation("...", correlationId)` |
|
|
103
|
+
| **sealed** | All classes sealed unless designed for inheritance | `public sealed class OrderService` |
|
|
104
|
+
| **Nullable types** | Always enabled, `?` only when truly optional | `string? middleName` (optional) vs `string name` (required) |
|
|
105
|
+
| **Primary constructors** | For DI injection (C# 12+) | `class OrderService(IRepo repo)` |
|
|
106
|
+
| **Expression body** | Single-line members | `public int Count => _items.Count;` |
|
|
107
|
+
| **Pattern matching** | `is null` / `is not null` | `if (order is null) return ...` |
|
|
108
|
+
| **Collection expressions** | Prefer `[..]` syntax | `List<int> ids = [1, 2, 3];` |
|
|
109
|
+
|
|
110
|
+
### Entity Pattern
|
|
111
|
+
|
|
112
|
+
```csharp
|
|
113
|
+
namespace MyApp.Domain.Entities;
|
|
114
|
+
|
|
115
|
+
public sealed class Order
|
|
116
|
+
{
|
|
117
|
+
// Private constructor — force factory method
|
|
118
|
+
private Order() { }
|
|
119
|
+
|
|
120
|
+
public Guid Id { get; private set; }
|
|
121
|
+
public int CustomerId { get; private set; }
|
|
122
|
+
public OrderStatus Status { get; private set; }
|
|
123
|
+
public decimal Total { get; private set; }
|
|
124
|
+
public DateTime CreatedAt { get; private set; }
|
|
125
|
+
|
|
126
|
+
// Factory method with validation
|
|
127
|
+
public static Order Create(int customerId, List<OrderItem> items)
|
|
128
|
+
{
|
|
129
|
+
if (items.Count == 0)
|
|
130
|
+
throw new DomainException("Order must have at least one item");
|
|
131
|
+
|
|
132
|
+
return new Order
|
|
133
|
+
{
|
|
134
|
+
Id = Guid.NewGuid(),
|
|
135
|
+
CustomerId = customerId,
|
|
136
|
+
Status = OrderStatus.Created,
|
|
137
|
+
Total = items.Sum(i => i.Price * i.Quantity),
|
|
138
|
+
CreatedAt = DateTime.UtcNow
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Behavior methods (not anemic)
|
|
143
|
+
public void MarkAsPaid()
|
|
144
|
+
{
|
|
145
|
+
if (Status >= OrderStatus.Completed || Status == OrderStatus.Failed)
|
|
146
|
+
throw new DomainException($"Cannot mark order {Id} as paid in status {Status}");
|
|
147
|
+
Status = OrderStatus.PendingPayment;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### DTO Pattern
|
|
153
|
+
|
|
154
|
+
```csharp
|
|
155
|
+
namespace MyApp.Application.DTOs;
|
|
156
|
+
|
|
157
|
+
// Request: record with required properties
|
|
158
|
+
public sealed record CreateOrderRequest(
|
|
159
|
+
int CustomerId,
|
|
160
|
+
List<OrderItemRequest> Items);
|
|
161
|
+
|
|
162
|
+
// Response: record with computed properties
|
|
163
|
+
public sealed record OrderResponse(
|
|
164
|
+
Guid Id,
|
|
165
|
+
int CustomerId,
|
|
166
|
+
string StatusDisplay,
|
|
167
|
+
decimal Total,
|
|
168
|
+
DateTime CreatedAt);
|
|
169
|
+
|
|
170
|
+
// Enum: PascalCase members, error states at 100+
|
|
171
|
+
public enum OrderStatus
|
|
172
|
+
{
|
|
173
|
+
Created = 0,
|
|
174
|
+
PendingPayment = 1,
|
|
175
|
+
Processing = 2,
|
|
176
|
+
Shipped = 3,
|
|
177
|
+
Completed = 4,
|
|
178
|
+
// Error states (high values for comparison operators)
|
|
179
|
+
Failed = 100,
|
|
180
|
+
Cancelled = 101,
|
|
181
|
+
Refunded = 102
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Post-Implementation Pipeline
|
|
188
|
+
|
|
189
|
+
After writing code, self-check before delivering:
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
1. NAMING CHECK → Does every identifier follow coding.md?
|
|
193
|
+
2. ARCHITECTURE → Are files in the correct layer? No forbidden references?
|
|
194
|
+
3. ASYNC → CancellationToken on all async? No .Result/.Wait()?
|
|
195
|
+
4. LOGGING → Entry/exit/error logging? Message templates (not $"")?
|
|
196
|
+
5. ERROR HANDLING → Result pattern for business? No empty catch?
|
|
197
|
+
6. SEALED → All classes sealed?
|
|
198
|
+
7. NULLABLE → <Nullable>enable</Nullable>? ? only where optional?
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Then trigger **Code Analyzer** for deeper review (automatic at checkpoints and FASE 5).
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Ultrathink Decision Template
|
|
206
|
+
|
|
207
|
+
When in Ultrathink Mode, produce structured analysis:
|
|
208
|
+
|
|
209
|
+
```markdown
|
|
210
|
+
## Decision: {Title}
|
|
211
|
+
|
|
212
|
+
### Context
|
|
213
|
+
{Why this decision is needed now. What triggered it. Current state.}
|
|
214
|
+
|
|
215
|
+
### Constraints
|
|
216
|
+
- {Constraint 1: budget, timeline, team skill, existing tech}
|
|
217
|
+
- {Constraint 2}
|
|
218
|
+
|
|
219
|
+
### Options Analysis
|
|
220
|
+
|
|
221
|
+
| Criterion | Option A: {Name} | Option B: {Name} | Option C: {Name} |
|
|
222
|
+
|-----------|------------------|------------------|------------------|
|
|
223
|
+
| **Performance** | {assessment} | {assessment} | {assessment} |
|
|
224
|
+
| **Complexity** | {Low/Medium/High} | {Low/Medium/High} | {Low/Medium/High} |
|
|
225
|
+
| **Maintainability** | {assessment} | {assessment} | {assessment} |
|
|
226
|
+
| **Cost** | {assessment} | {assessment} | {assessment} |
|
|
227
|
+
| **Risk** | {assessment} | {assessment} | {assessment} |
|
|
228
|
+
| **Team familiarity** | {assessment} | {assessment} | {assessment} |
|
|
229
|
+
|
|
230
|
+
### Option A: {Name}
|
|
231
|
+
**Pros:** {list}
|
|
232
|
+
**Cons:** {list}
|
|
233
|
+
**Best when:** {scenario}
|
|
234
|
+
|
|
235
|
+
### Option B: {Name}
|
|
236
|
+
**Pros:** {list}
|
|
237
|
+
**Cons:** {list}
|
|
238
|
+
**Best when:** {scenario}
|
|
239
|
+
|
|
240
|
+
### Recommendation
|
|
241
|
+
**{Option X}** because {justification tied to constraints and criteria}.
|
|
242
|
+
|
|
243
|
+
### Implementation Impact
|
|
244
|
+
- **Files affected:** {count and key files}
|
|
245
|
+
- **Migrations:** {yes/no, what changes}
|
|
246
|
+
- **Breaking changes:** {yes/no, what breaks}
|
|
247
|
+
- **Estimated effort:** {T-shirt size with rationale}
|
|
248
|
+
- **Rollback plan:** {how to revert if needed}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## .NET 10 / C# 14 Quick Patterns
|
|
254
|
+
|
|
255
|
+
| Pattern | When | Example |
|
|
256
|
+
|---------|------|---------|
|
|
257
|
+
| Primary constructors | DI injection | `class Service(IRepo repo)` |
|
|
258
|
+
| Collection expressions | Initialize collections | `List<int> ids = [1, 2, 3]` |
|
|
259
|
+
| File-scoped namespaces | Always | `namespace MyApp.Services;` |
|
|
260
|
+
| Raw string literals | Multi-line strings, SQL | `"""SELECT * FROM ..."""` |
|
|
261
|
+
| Records | Immutable DTOs | `record OrderResponse(Guid Id, ...)` |
|
|
262
|
+
| Pattern matching | Type checks, null checks | `if (x is Order { Status: > 0 } order)` |
|
|
263
|
+
| `required` modifier | Non-nullable init props | `public required string Name { get; init; }` |
|
|
264
|
+
| `sealed` classes | Default for all classes | `public sealed class OrderService` |
|
|
265
|
+
| Extension methods | Add behavior to existing types | `public static class OrderExtensions` |
|
|
266
|
+
| Global usings | Reduce repetitive imports | `global using MyApp.Domain.Entities;` |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Anti-Patterns to NEVER Produce
|
|
271
|
+
|
|
272
|
+
| Anti-Pattern | Why | Instead |
|
|
273
|
+
|--------------|-----|---------|
|
|
274
|
+
| `async void` | Exceptions lost, can't await | `async Task` (always) |
|
|
275
|
+
| `.Result` / `.Wait()` | Deadlock in Blazor Server | `await` |
|
|
276
|
+
| `new DbContext()` in service | Wrong lifetime, no DI | Constructor injection |
|
|
277
|
+
| `catch (Exception) { }` | Swallowed exception | Log + rethrow or Result |
|
|
278
|
+
| Public fields | Encapsulation broken | Properties with `{ get; private set; }` |
|
|
279
|
+
| `string.Format` in logs | Defeats structured logging | Message templates |
|
|
280
|
+
| `== null` | Not idiomatic C# | `is null` |
|
|
281
|
+
| Unsealed classes | Unintended inheritance | `sealed` keyword |
|
|
282
|
+
| Service Locator | Hidden dependencies | Constructor injection |
|
|
283
|
+
| God class (500+ lines) | Unmaintainable | Split by responsibility |
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,200 +1,113 @@
|
|
|
1
|
-
# EF Modeler
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
public
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
public
|
|
25
|
-
public
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
public
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
# Aplicar migration
|
|
115
|
-
dotnet ef database update
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Convenções de Naming
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
{YYYYMMDD}_{Numero}_{Descricao}
|
|
122
|
-
|
|
123
|
-
Exemplos:
|
|
124
|
-
- 20240301_001_CreateOrdersTable
|
|
125
|
-
- 20240301_002_AddCustomerIdToOrders
|
|
126
|
-
- 20240302_001_CreateIndexOnOrderNumber
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Queries Otimizadas
|
|
130
|
-
|
|
131
|
-
```csharp
|
|
132
|
-
// RUIM: N+1 problem
|
|
133
|
-
var orders = await _context.Orders.ToListAsync();
|
|
134
|
-
foreach (var order in orders)
|
|
135
|
-
{
|
|
136
|
-
var items = order.Items; // N queries adicionais!
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// BOM: Include explicito
|
|
140
|
-
var orders = await _context.Orders
|
|
141
|
-
.Include(o => o.Items)
|
|
142
|
-
.Include(o => o.Customer)
|
|
143
|
-
.ToListAsync();
|
|
144
|
-
|
|
145
|
-
// MELHOR: Projection
|
|
146
|
-
var orderDtos = await _context.Orders
|
|
147
|
-
.Select(o => new OrderDto
|
|
148
|
-
{
|
|
149
|
-
Id = o.Id,
|
|
150
|
-
OrderNumber = o.OrderNumber,
|
|
151
|
-
CustomerName = o.Customer.Name,
|
|
152
|
-
ItemCount = o.Items.Count,
|
|
153
|
-
Total = o.Total
|
|
154
|
-
})
|
|
155
|
-
.ToListAsync();
|
|
156
|
-
|
|
157
|
-
// Paginação
|
|
158
|
-
var pagedOrders = await _context.Orders
|
|
159
|
-
.OrderByDescending(o => o.CreatedAt)
|
|
160
|
-
.Skip((page - 1) * pageSize)
|
|
161
|
-
.Take(pageSize)
|
|
162
|
-
.ToListAsync();
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## Padrões de Repository (Opcional)
|
|
166
|
-
|
|
167
|
-
```csharp
|
|
168
|
-
// Se usar repository pattern
|
|
169
|
-
public interface IOrderRepository
|
|
170
|
-
{
|
|
171
|
-
Task<Order?> GetByIdAsync(int id, CancellationToken ct = default);
|
|
172
|
-
Task<Order?> GetByOrderNumberAsync(string orderNumber, CancellationToken ct = default);
|
|
173
|
-
Task<IReadOnlyList<Order>> GetByCustomerIdAsync(int customerId, CancellationToken ct = default);
|
|
174
|
-
Task AddAsync(Order order, CancellationToken ct = default);
|
|
175
|
-
void Update(Order order);
|
|
176
|
-
void Remove(Order order);
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Documentação de Referência
|
|
181
|
-
|
|
182
|
-
- [EF Core Docs](https://learn.microsoft.com/en-us/ef/core/)
|
|
183
|
-
- [Migrations](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/)
|
|
184
|
-
- [Performance](https://learn.microsoft.com/en-us/ef/core/performance/)
|
|
185
|
-
- [Relationships](https://learn.microsoft.com/en-us/ef/core/modeling/relationships/)
|
|
186
|
-
|
|
187
|
-
## Checklist de Modelagem
|
|
188
|
-
|
|
189
|
-
- [ ] Entidades com private setters
|
|
190
|
-
- [ ] Factory methods para criação
|
|
191
|
-
- [ ] Configuração separada (IEntityTypeConfiguration)
|
|
192
|
-
- [ ] Índices em colunas de busca
|
|
193
|
-
- [ ] Precision definida para decimais
|
|
194
|
-
- [ ] Delete behavior explícito
|
|
195
|
-
- [ ] Migration script gerado e revisado
|
|
196
|
-
- [ ] Queries com Include ou Projection
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
*MORPH-SPEC by Polymorphism Tech*
|
|
1
|
+
# EF Modeler
|
|
2
|
+
|
|
3
|
+
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** entity, database, migration, ef core, dbcontext, table, column, relationship, query
|
|
4
|
+
|
|
5
|
+
Especialista em Entity Framework Core para modelagem de dados e banco de dados.
|
|
6
|
+
|
|
7
|
+
## .NET 10 Compatibility
|
|
8
|
+
- EF Core: **>= 10.0.0** | New: Vector search, primitive collections
|
|
9
|
+
- **Ref:** `framework/standards/dotnet10-compatibility.md`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Entity Structure
|
|
14
|
+
|
|
15
|
+
```csharp
|
|
16
|
+
public class Order : BaseEntity
|
|
17
|
+
{
|
|
18
|
+
public string OrderNumber { get; private set; } = null!;
|
|
19
|
+
public OrderStatus Status { get; private set; }
|
|
20
|
+
public decimal Total { get; private set; }
|
|
21
|
+
public DateTime CreatedAt { get; private set; }
|
|
22
|
+
|
|
23
|
+
// Navigation
|
|
24
|
+
public int CustomerId { get; private set; }
|
|
25
|
+
public Customer Customer { get; private set; } = null!;
|
|
26
|
+
public ICollection<OrderItem> Items { get; private set; } = new List<OrderItem>();
|
|
27
|
+
|
|
28
|
+
// Factory method
|
|
29
|
+
public static Order Create(int customerId, IEnumerable<OrderItem> items) { ... }
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Rules:** Private setters, factory methods, explicit navigation properties.
|
|
34
|
+
|
|
35
|
+
## Configuration
|
|
36
|
+
|
|
37
|
+
```csharp
|
|
38
|
+
public class OrderConfiguration : IEntityTypeConfiguration<Order>
|
|
39
|
+
{
|
|
40
|
+
public void Configure(EntityTypeBuilder<Order> builder)
|
|
41
|
+
{
|
|
42
|
+
builder.ToTable("Orders");
|
|
43
|
+
builder.HasKey(o => o.Id);
|
|
44
|
+
builder.Property(o => o.OrderNumber).IsRequired().HasMaxLength(20);
|
|
45
|
+
builder.Property(o => o.Total).HasPrecision(18, 2);
|
|
46
|
+
builder.HasIndex(o => o.OrderNumber).IsUnique();
|
|
47
|
+
builder.HasOne(o => o.Customer).WithMany(c => c.Orders)
|
|
48
|
+
.HasForeignKey(o => o.CustomerId).OnDelete(DeleteBehavior.Restrict);
|
|
49
|
+
builder.HasMany(o => o.Items).WithOne(i => i.Order)
|
|
50
|
+
.HasForeignKey(i => i.OrderId).OnDelete(DeleteBehavior.Cascade);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Migrations
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
dotnet ef migrations add {Name} --project src/Infrastructure --startup-project src/Web
|
|
59
|
+
dotnet ef migrations script --idempotent --output migration.sql
|
|
60
|
+
dotnet ef database update
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Naming:** `{YYYYMMDD}_{Number}_{Description}` (e.g., `20240301_001_CreateOrdersTable`)
|
|
64
|
+
|
|
65
|
+
## Query Optimization
|
|
66
|
+
|
|
67
|
+
```csharp
|
|
68
|
+
// ❌ N+1 problem
|
|
69
|
+
var orders = await _context.Orders.ToListAsync();
|
|
70
|
+
foreach (var o in orders) { var items = o.Items; } // N extra queries!
|
|
71
|
+
|
|
72
|
+
// ✅ Include
|
|
73
|
+
var orders = await _context.Orders.Include(o => o.Items).Include(o => o.Customer).ToListAsync();
|
|
74
|
+
|
|
75
|
+
// ✅ Projection (best)
|
|
76
|
+
var dtos = await _context.Orders.Select(o => new OrderDto {
|
|
77
|
+
Id = o.Id, CustomerName = o.Customer.Name, ItemCount = o.Items.Count
|
|
78
|
+
}).ToListAsync();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Background Operations
|
|
84
|
+
|
|
85
|
+
> **Ref:** `framework/standards/blazor-efcore.md` — Repository Factory pattern for background ops
|
|
86
|
+
|
|
87
|
+
**Rule:** Separate thread = isolated DbContext via `IDbContextFactory`.
|
|
88
|
+
Background tasks, `Task.Run`, SignalR, Hangfire jobs — all need `IDbContextFactory`.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
| Error | Cause | Fix |
|
|
95
|
+
|-------|-------|-----|
|
|
96
|
+
| `Invalid object name 'Table'` | Migration not applied | Run `database update` |
|
|
97
|
+
| `PendingModelChangesWarning` | Model changed without migration | Create new migration |
|
|
98
|
+
| `Include() doesn't load` | `HasMany<T>()` without navigation | Use `HasMany(x => x.Nav)` |
|
|
99
|
+
| `A second operation was started` | Shared DbContext | Use `IDbContextFactory` |
|
|
100
|
+
|
|
101
|
+
## Checklist
|
|
102
|
+
- [ ] Entities with private setters + factory methods
|
|
103
|
+
- [ ] Separate configuration (IEntityTypeConfiguration)
|
|
104
|
+
- [ ] Indexes on search columns
|
|
105
|
+
- [ ] Precision defined for decimals
|
|
106
|
+
- [ ] Delete behavior explicit
|
|
107
|
+
- [ ] Migration script generated and reviewed
|
|
108
|
+
- [ ] Queries with Include or Projection (no N+1)
|
|
109
|
+
- [ ] `IDbContextFactory` for background ops
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
*MORPH-SPEC by Polymorphism Tech*
|