@polymorphism-tech/morph-spec 1.0.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.
Files changed (83) hide show
  1. package/README.md +279 -0
  2. package/bin/morph-spec.js +53 -0
  3. package/content/.claude/commands/morph-apply.md +66 -0
  4. package/content/.claude/commands/morph-archive.md +79 -0
  5. package/content/.claude/commands/morph-costs.md +206 -0
  6. package/content/.claude/commands/morph-infra.md +209 -0
  7. package/content/.claude/commands/morph-proposal.md +60 -0
  8. package/content/.claude/commands/morph-status.md +71 -0
  9. package/content/.claude/settings.local.json +15 -0
  10. package/content/.claude/skills/infra/bicep-architect.md +419 -0
  11. package/content/.claude/skills/infra/container-specialist.md +437 -0
  12. package/content/.claude/skills/infra/devops-engineer.md +405 -0
  13. package/content/.claude/skills/integrations/asaas-financial.md +333 -0
  14. package/content/.claude/skills/integrations/azure-identity.md +309 -0
  15. package/content/.claude/skills/integrations/clerk-auth.md +290 -0
  16. package/content/.claude/skills/specialists/azure-architect.md +142 -0
  17. package/content/.claude/skills/specialists/cost-guardian.md +110 -0
  18. package/content/.claude/skills/specialists/ef-modeler.md +200 -0
  19. package/content/.claude/skills/specialists/hangfire-orchestrator.md +245 -0
  20. package/content/.claude/skills/specialists/ms-agent-expert.md +209 -0
  21. package/content/.claude/skills/specialists/po-pm-advisor.md +197 -0
  22. package/content/.claude/skills/specialists/standards-architect.md +78 -0
  23. package/content/.claude/skills/specialists/ui-ux-designer.md +325 -0
  24. package/content/.claude/skills/stacks/dotnet-blazor.md +352 -0
  25. package/content/.claude/skills/stacks/dotnet-nextjs.md +402 -0
  26. package/content/.claude/skills/stacks/shopify.md +445 -0
  27. package/content/.morph/archive/.gitkeep +25 -0
  28. package/content/.morph/config/agents.json +149 -0
  29. package/content/.morph/config/config.template.json +96 -0
  30. package/content/.morph/examples/api-nextjs/README.md +241 -0
  31. package/content/.morph/examples/api-nextjs/contracts.ts +307 -0
  32. package/content/.morph/examples/api-nextjs/spec.md +399 -0
  33. package/content/.morph/examples/api-nextjs/tasks.md +168 -0
  34. package/content/.morph/examples/micro-saas/README.md +125 -0
  35. package/content/.morph/examples/micro-saas/contracts.cs +358 -0
  36. package/content/.morph/examples/micro-saas/decisions.md +246 -0
  37. package/content/.morph/examples/micro-saas/spec.md +236 -0
  38. package/content/.morph/examples/micro-saas/tasks.md +150 -0
  39. package/content/.morph/examples/multi-agent/README.md +309 -0
  40. package/content/.morph/examples/multi-agent/contracts.cs +433 -0
  41. package/content/.morph/examples/multi-agent/spec.md +479 -0
  42. package/content/.morph/examples/multi-agent/tasks.md +185 -0
  43. package/content/.morph/features/.gitkeep +25 -0
  44. package/content/.morph/project.md +159 -0
  45. package/content/.morph/specs/.gitkeep +20 -0
  46. package/content/.morph/standards/architecture.md +190 -0
  47. package/content/.morph/standards/azure.md +184 -0
  48. package/content/.morph/standards/coding.md +342 -0
  49. package/content/.morph/templates/agent.cs +172 -0
  50. package/content/.morph/templates/component.razor +239 -0
  51. package/content/.morph/templates/contracts.cs +217 -0
  52. package/content/.morph/templates/decisions.md +106 -0
  53. package/content/.morph/templates/infra/app-insights.bicep +63 -0
  54. package/content/.morph/templates/infra/container-app-env.bicep +49 -0
  55. package/content/.morph/templates/infra/container-app.bicep +156 -0
  56. package/content/.morph/templates/infra/key-vault.bicep +91 -0
  57. package/content/.morph/templates/infra/main.bicep +155 -0
  58. package/content/.morph/templates/infra/parameters.dev.json +23 -0
  59. package/content/.morph/templates/infra/parameters.prod.json +23 -0
  60. package/content/.morph/templates/infra/sql-database.bicep +103 -0
  61. package/content/.morph/templates/infra/storage.bicep +106 -0
  62. package/content/.morph/templates/integrations/asaas-client.cs +387 -0
  63. package/content/.morph/templates/integrations/asaas-webhook.cs +351 -0
  64. package/content/.morph/templates/integrations/azure-identity-config.cs +288 -0
  65. package/content/.morph/templates/integrations/clerk-config.cs +258 -0
  66. package/content/.morph/templates/job.cs +171 -0
  67. package/content/.morph/templates/migration.cs +83 -0
  68. package/content/.morph/templates/proposal.md +155 -0
  69. package/content/.morph/templates/recap.md +105 -0
  70. package/content/.morph/templates/repository.cs +141 -0
  71. package/content/.morph/templates/saas/subscription.cs +347 -0
  72. package/content/.morph/templates/saas/tenant.cs +338 -0
  73. package/content/.morph/templates/service.cs +139 -0
  74. package/content/.morph/templates/spec.md +147 -0
  75. package/content/.morph/templates/tasks.md +235 -0
  76. package/content/.morph/templates/test.cs +239 -0
  77. package/content/CLAUDE.md +318 -0
  78. package/package.json +50 -0
  79. package/src/commands/doctor.js +132 -0
  80. package/src/commands/init.js +121 -0
  81. package/src/commands/update.js +84 -0
  82. package/src/utils/file-copier.js +50 -0
  83. package/src/utils/logger.js +32 -0
@@ -0,0 +1,235 @@
1
+ # Tasks - {FEATURE_NAME}
2
+
3
+ > Checklist de implementação para a feature.
4
+ > Atualize o status conforme progresso.
5
+
6
+ ## Summary
7
+
8
+ | Metric | Value |
9
+ |--------|-------|
10
+ | **Total Tasks** | 0 |
11
+ | **Completed** | 0 |
12
+ | **In Progress** | 0 |
13
+ | **Pending** | 0 |
14
+ | **Estimated** | 0h |
15
+ | **Actual** | 0h |
16
+
17
+ ---
18
+
19
+ ## Checkpoints
20
+
21
+ | After | Type | Description | Status |
22
+ |-------|------|-------------|--------|
23
+ | T003 | Review | Review contracts and data model | Pending |
24
+ | T006 | Review | Review service implementation | Pending |
25
+ | T009 | Approval | Approve UI before tests | Pending |
26
+
27
+ ---
28
+
29
+ ## Phase 1: Contracts & Data Model
30
+
31
+ ### T001: Define service interfaces
32
+ - **Type:** Contract
33
+ - **Priority:** 1
34
+ - **Estimate:** 30min
35
+ - **Status:** [ ] Pending
36
+
37
+ **Description:**
38
+ Create I{Feature}Service interface with all required methods.
39
+
40
+ **Acceptance Criteria:**
41
+ - [ ] Interface follows naming conventions
42
+ - [ ] All CRUD methods defined
43
+ - [ ] Async methods with CancellationToken
44
+
45
+ **Files:**
46
+ - [ ] Create: `Application/Features/{Feature}/Services/I{Feature}Service.cs`
47
+
48
+ ---
49
+
50
+ ### T002: Define repository interfaces
51
+ - **Type:** Contract
52
+ - **Priority:** 1
53
+ - **Estimate:** 20min
54
+ - **Status:** [ ] Pending
55
+
56
+ **Description:**
57
+ Create I{Feature}Repository interface.
58
+
59
+ **Files:**
60
+ - [ ] Create: `Application/Features/{Feature}/Services/I{Feature}Repository.cs`
61
+
62
+ ---
63
+
64
+ ### T003: Create domain entities
65
+ - **Type:** Domain
66
+ - **Priority:** 1
67
+ - **Estimate:** 45min
68
+ - **Status:** [ ] Pending
69
+ - **Checkpoint:** Review after this task
70
+
71
+ **Description:**
72
+ Create {Feature} entity with factory methods.
73
+
74
+ **Files:**
75
+ - [ ] Create: `Domain/Entities/{Feature}.cs`
76
+
77
+ ---
78
+
79
+ ## Phase 2: Infrastructure
80
+
81
+ ### T004: Create EF configuration and migration
82
+ - **Type:** Infrastructure
83
+ - **Priority:** 2
84
+ - **Estimate:** 30min
85
+ - **Status:** [ ] Pending
86
+ - **Dependencies:** T003
87
+
88
+ **Description:**
89
+ Configure entity mapping and create migration.
90
+
91
+ **Files:**
92
+ - [ ] Create: `Infrastructure/Data/Configurations/{Feature}Configuration.cs`
93
+ - [ ] Create: `Infrastructure/Data/Migrations/{timestamp}_Add{Feature}.cs`
94
+ - [ ] Modify: `Infrastructure/Data/AppDbContext.cs`
95
+
96
+ ---
97
+
98
+ ### T005: Implement repository
99
+ - **Type:** Infrastructure
100
+ - **Priority:** 2
101
+ - **Estimate:** 45min
102
+ - **Status:** [ ] Pending
103
+ - **Dependencies:** T002, T004
104
+
105
+ **Description:**
106
+ Implement I{Feature}Repository.
107
+
108
+ **Files:**
109
+ - [ ] Create: `Infrastructure/Data/Repositories/{Feature}Repository.cs`
110
+
111
+ ---
112
+
113
+ ## Phase 3: Implementation
114
+
115
+ ### T006: Implement service layer
116
+ - **Type:** Service
117
+ - **Priority:** 2
118
+ - **Estimate:** 1h
119
+ - **Status:** [ ] Pending
120
+ - **Dependencies:** T001, T005
121
+ - **Checkpoint:** Review after this task
122
+
123
+ **Description:**
124
+ Implement I{Feature}Service with business logic.
125
+
126
+ **Files:**
127
+ - [ ] Create: `Application/Features/{Feature}/Services/{Feature}Service.cs`
128
+
129
+ ---
130
+
131
+ ### T007: Implement AI agent (if applicable)
132
+ - **Type:** Agent
133
+ - **Priority:** 3
134
+ - **Estimate:** 1h
135
+ - **Status:** [ ] Pending
136
+ - **Dependencies:** T006
137
+
138
+ **Description:**
139
+ Create AI agent for analysis/processing.
140
+
141
+ **Files:**
142
+ - [ ] Create: `Agents/{Feature}Analyzer/{Feature}AnalyzerAgent.cs`
143
+
144
+ ---
145
+
146
+ ### T008: Implement background job (if applicable)
147
+ - **Type:** Job
148
+ - **Priority:** 3
149
+ - **Estimate:** 45min
150
+ - **Status:** [ ] Pending
151
+ - **Dependencies:** T006
152
+
153
+ **Description:**
154
+ Create Hangfire job for scheduled processing.
155
+
156
+ **Files:**
157
+ - [ ] Create: `Application/Features/{Feature}/Jobs/{Feature}ProcessorJob.cs`
158
+
159
+ ---
160
+
161
+ ## Phase 4: UI Components
162
+
163
+ ### T009: Create list component
164
+ - **Type:** UI
165
+ - **Priority:** 2
166
+ - **Estimate:** 1h
167
+ - **Status:** [ ] Pending
168
+ - **Dependencies:** T006
169
+ - **Checkpoint:** Approval after this task
170
+
171
+ **Description:**
172
+ Create Blazor component to list items.
173
+
174
+ **Files:**
175
+ - [ ] Create: `Web/Components/Pages/{Feature}/{Feature}List.razor`
176
+
177
+ ---
178
+
179
+ ### T010: Create form component
180
+ - **Type:** UI
181
+ - **Priority:** 2
182
+ - **Estimate:** 1h
183
+ - **Status:** [ ] Pending
184
+ - **Dependencies:** T009
185
+
186
+ **Description:**
187
+ Create Blazor component for create/edit.
188
+
189
+ **Files:**
190
+ - [ ] Create: `Web/Components/Pages/{Feature}/{Feature}Form.razor`
191
+
192
+ ---
193
+
194
+ ## Phase 5: Testing
195
+
196
+ ### T011: Write unit tests
197
+ - **Type:** Test
198
+ - **Priority:** 2
199
+ - **Estimate:** 1h
200
+ - **Status:** [ ] Pending
201
+ - **Dependencies:** T006
202
+
203
+ **Description:**
204
+ Unit tests for service layer.
205
+
206
+ **Files:**
207
+ - [ ] Create: `Tests/Unit/{Feature}ServiceTests.cs`
208
+
209
+ ---
210
+
211
+ ### T012: Write integration tests
212
+ - **Type:** Test
213
+ - **Priority:** 3
214
+ - **Estimate:** 1h
215
+ - **Status:** [ ] Pending
216
+ - **Dependencies:** T011
217
+
218
+ **Description:**
219
+ Integration tests for repository and API.
220
+
221
+ **Files:**
222
+ - [ ] Create: `Tests/Integration/{Feature}IntegrationTests.cs`
223
+
224
+ ---
225
+
226
+ ## Status Legend
227
+
228
+ - [ ] Pending
229
+ - [~] In Progress
230
+ - [x] Completed
231
+ - [!] Blocked
232
+
233
+ ---
234
+
235
+ *Generated by MORPH Framework*
@@ -0,0 +1,239 @@
1
+ // ============================================================
2
+ // TEST TEMPLATE
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using FluentAssertions;
7
+ using Microsoft.Extensions.Logging;
8
+ using NSubstitute;
9
+ using Xunit;
10
+
11
+ namespace MyProject.Tests.Unit.Features.{Feature};
12
+
13
+ /// <summary>
14
+ /// Unit tests for {Feature}Service.
15
+ /// </summary>
16
+ public class {Feature}ServiceTests
17
+ {
18
+ private readonly I{Feature}Repository _repository;
19
+ private readonly ILogger<{Feature}Service> _logger;
20
+ private readonly {Feature}Service _sut;
21
+
22
+ public {Feature}ServiceTests()
23
+ {
24
+ _repository = Substitute.For<I{Feature}Repository>();
25
+ _logger = Substitute.For<ILogger<{Feature}Service>>();
26
+ _sut = new {Feature}Service(_repository, _logger);
27
+ }
28
+
29
+ #region GetByIdAsync Tests
30
+
31
+ [Fact]
32
+ public async Task GetByIdAsync_WithValidId_ReturnsDto()
33
+ {
34
+ // Arrange
35
+ var id = 1;
36
+ var entity = CreateTestEntity(id, "Test {Feature}");
37
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
38
+ .Returns(entity);
39
+
40
+ // Act
41
+ var result = await _sut.GetByIdAsync(id);
42
+
43
+ // Assert
44
+ result.Should().NotBeNull();
45
+ result!.Id.Should().Be(id);
46
+ result.Name.Should().Be("Test {Feature}");
47
+ }
48
+
49
+ [Fact]
50
+ public async Task GetByIdAsync_WithInvalidId_ReturnsNull()
51
+ {
52
+ // Arrange
53
+ var id = 999;
54
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
55
+ .Returns((Domain.Entities.{Feature}?)null);
56
+
57
+ // Act
58
+ var result = await _sut.GetByIdAsync(id);
59
+
60
+ // Assert
61
+ result.Should().BeNull();
62
+ }
63
+
64
+ #endregion
65
+
66
+ #region GetAllAsync Tests
67
+
68
+ [Fact]
69
+ public async Task GetAllAsync_ReturnsAllItems()
70
+ {
71
+ // Arrange
72
+ var entities = new List<Domain.Entities.{Feature}>
73
+ {
74
+ CreateTestEntity(1, "First"),
75
+ CreateTestEntity(2, "Second"),
76
+ CreateTestEntity(3, "Third")
77
+ };
78
+ _repository.GetAllAsync(Arg.Any<CancellationToken>())
79
+ .Returns(entities);
80
+
81
+ // Act
82
+ var result = await _sut.GetAllAsync();
83
+
84
+ // Assert
85
+ result.Should().HaveCount(3);
86
+ result[0].Name.Should().Be("First");
87
+ }
88
+
89
+ [Fact]
90
+ public async Task GetAllAsync_WithNoItems_ReturnsEmptyList()
91
+ {
92
+ // Arrange
93
+ _repository.GetAllAsync(Arg.Any<CancellationToken>())
94
+ .Returns(new List<Domain.Entities.{Feature}>());
95
+
96
+ // Act
97
+ var result = await _sut.GetAllAsync();
98
+
99
+ // Assert
100
+ result.Should().BeEmpty();
101
+ }
102
+
103
+ #endregion
104
+
105
+ #region CreateAsync Tests
106
+
107
+ [Fact]
108
+ public async Task CreateAsync_WithValidRequest_CreatesAndReturnsDto()
109
+ {
110
+ // Arrange
111
+ var request = new Create{Feature}Request("New {Feature}");
112
+
113
+ _repository
114
+ .When(x => x.AddAsync(Arg.Any<Domain.Entities.{Feature}>(), Arg.Any<CancellationToken>()))
115
+ .Do(x =>
116
+ {
117
+ // Simulate ID assignment
118
+ var entity = x.Arg<Domain.Entities.{Feature}>();
119
+ // entity.Id would be set by EF Core
120
+ });
121
+
122
+ // Act
123
+ var result = await _sut.CreateAsync(request);
124
+
125
+ // Assert
126
+ result.Should().NotBeNull();
127
+ result.Name.Should().Be("New {Feature}");
128
+
129
+ await _repository.Received(1).AddAsync(Arg.Any<Domain.Entities.{Feature}>(), Arg.Any<CancellationToken>());
130
+ await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
131
+ }
132
+
133
+ [Theory]
134
+ [InlineData("")]
135
+ [InlineData(" ")]
136
+ [InlineData(null)]
137
+ public async Task CreateAsync_WithInvalidName_ThrowsValidationException(string? name)
138
+ {
139
+ // Arrange
140
+ var request = new Create{Feature}Request(name!);
141
+
142
+ // Act
143
+ var act = async () => await _sut.CreateAsync(request);
144
+
145
+ // Assert
146
+ await act.Should().ThrowAsync<ValidationException>();
147
+ }
148
+
149
+ #endregion
150
+
151
+ #region UpdateAsync Tests
152
+
153
+ [Fact]
154
+ public async Task UpdateAsync_WithValidRequest_UpdatesEntity()
155
+ {
156
+ // Arrange
157
+ var id = 1;
158
+ var entity = CreateTestEntity(id, "Original");
159
+ var request = new Update{Feature}Request("Updated");
160
+
161
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
162
+ .Returns(entity);
163
+
164
+ // Act
165
+ await _sut.UpdateAsync(id, request);
166
+
167
+ // Assert
168
+ _repository.Received(1).Update(Arg.Any<Domain.Entities.{Feature}>());
169
+ await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
170
+ }
171
+
172
+ [Fact]
173
+ public async Task UpdateAsync_WithNonExistentId_ThrowsNotFoundException()
174
+ {
175
+ // Arrange
176
+ var id = 999;
177
+ var request = new Update{Feature}Request("Updated");
178
+
179
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
180
+ .Returns((Domain.Entities.{Feature}?)null);
181
+
182
+ // Act
183
+ var act = async () => await _sut.UpdateAsync(id, request);
184
+
185
+ // Assert
186
+ await act.Should().ThrowAsync<{Feature}NotFoundException>();
187
+ }
188
+
189
+ #endregion
190
+
191
+ #region DeleteAsync Tests
192
+
193
+ [Fact]
194
+ public async Task DeleteAsync_WithValidId_DeletesEntity()
195
+ {
196
+ // Arrange
197
+ var id = 1;
198
+ var entity = CreateTestEntity(id, "To Delete");
199
+
200
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
201
+ .Returns(entity);
202
+
203
+ // Act
204
+ await _sut.DeleteAsync(id);
205
+
206
+ // Assert
207
+ _repository.Received(1).Remove(entity);
208
+ await _repository.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
209
+ }
210
+
211
+ [Fact]
212
+ public async Task DeleteAsync_WithNonExistentId_ThrowsNotFoundException()
213
+ {
214
+ // Arrange
215
+ var id = 999;
216
+
217
+ _repository.GetByIdAsync(id, Arg.Any<CancellationToken>())
218
+ .Returns((Domain.Entities.{Feature}?)null);
219
+
220
+ // Act
221
+ var act = async () => await _sut.DeleteAsync(id);
222
+
223
+ // Assert
224
+ await act.Should().ThrowAsync<{Feature}NotFoundException>();
225
+ }
226
+
227
+ #endregion
228
+
229
+ #region Helper Methods
230
+
231
+ private static Domain.Entities.{Feature} CreateTestEntity(int id, string name)
232
+ {
233
+ return Domain.Entities.{Feature}.Create(name);
234
+ // Note: In real tests, you might need reflection to set the Id
235
+ // or use a factory method that accepts an id for testing
236
+ }
237
+
238
+ #endregion
239
+ }