@polymorphism-tech/morph-spec 4.22.0 → 5.0.1

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 (211) hide show
  1. package/CLAUDE.md +57 -71
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +224 -491
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +55 -38
  8. package/framework/MORPH.md +244 -0
  9. package/framework/agents.json +127 -1198
  10. package/framework/commands/morph-apply.md +56 -240
  11. package/framework/commands/morph-archive.md +48 -85
  12. package/framework/commands/morph-preflight.md +7 -7
  13. package/framework/commands/morph-proposal.md +35 -191
  14. package/framework/commands/morph-status.md +19 -50
  15. package/framework/commands/morph-troubleshoot.md +2 -2
  16. package/framework/evals/rubrics/README.md +44 -0
  17. package/framework/evals/rubrics/architecture.md +46 -0
  18. package/framework/evals/rubrics/code-quality.md +50 -0
  19. package/framework/evals/rubrics/contracts.md +47 -0
  20. package/framework/evals/rubrics/test-coverage.md +50 -0
  21. package/framework/evals/scenarios/dotnet-crud.yaml +42 -0
  22. package/framework/evals/scenarios/nextjs-auth.yaml +38 -0
  23. package/framework/evals/suites/standard.yaml +5 -0
  24. package/framework/evals/trace-schema.md +67 -0
  25. package/framework/hooks/claude-code/core/README.md +3 -0
  26. package/framework/hooks/claude-code/core/denylist.json +14 -0
  27. package/framework/hooks/claude-code/{pre-tool-use → core}/enforce-phase-writes.js +5 -5
  28. package/framework/hooks/claude-code/core/post-edit-typecheck.js +69 -0
  29. package/framework/hooks/claude-code/core/pre-bash-denylist.js +29 -0
  30. package/framework/hooks/claude-code/{pre-tool-use → core}/protect-spec-files.js +4 -6
  31. package/framework/hooks/claude-code/{stop → core}/validate-completion.js +13 -82
  32. package/framework/hooks/shared/phase-utils.js +20 -31
  33. package/framework/hooks/shared/state-reader.js +4 -5
  34. package/framework/{skills/level-0-meta/mcp-registry.json → mcp/registry.json} +254 -243
  35. package/framework/phases.json +41 -115
  36. package/framework/rubrics/eval-rubric.json +66 -0
  37. package/framework/skills/README.md +39 -64
  38. package/framework/skills/core/README.md +3 -0
  39. package/framework/skills/core/morph-brainstorming/SKILL.md +102 -0
  40. package/framework/skills/core/morph-eval/SKILL.md +57 -0
  41. package/framework/skills/core/morph-implement/SKILL.md +83 -0
  42. package/framework/skills/core/morph-plan/SKILL.md +64 -0
  43. package/framework/skills/core/morph-review/SKILL.md +62 -0
  44. package/framework/skills/core/morph-stack-scan/SKILL.md +109 -0
  45. package/framework/skills/core/morph-standards/SKILL.md +49 -0
  46. package/framework/templates/CLAUDE.md.core.guide.md +29 -0
  47. package/framework/templates/CLAUDE.md.core.template +22 -0
  48. package/framework/templates/REGISTRY.json +4 -4
  49. package/framework/workflows/configs/fast-track.json +5 -10
  50. package/framework/workflows/configs/full.json +4 -8
  51. package/framework/workflows/configs/quick.json +32 -0
  52. package/framework/workflows/configs/standard.json +57 -64
  53. package/package.json +7 -6
  54. package/src/commands/mcp/mcp-setup.js +58 -31
  55. package/src/commands/project/doctor.js +69 -70
  56. package/src/commands/project/init.js +26 -5
  57. package/src/commands/project/status.js +18 -19
  58. package/src/commands/state/approve.js +1 -1
  59. package/src/commands/validation/validate-feature.js +18 -112
  60. package/src/core/paths/output-schema.js +133 -152
  61. package/src/core/state/phase-state-machine.js +10 -24
  62. package/src/core/state/state-manager.js +17 -17
  63. package/src/core/workflows/workflow-detector.js +214 -31
  64. package/src/core/workflows/workflow-router.js +204 -0
  65. package/src/dashboard/app/pages/AgentMap.jsx +32 -33
  66. package/src/dashboard/app/pages/LiveState.jsx +1 -1
  67. package/src/dashboard/app/pages/PhasePipeline.jsx +2 -4
  68. package/src/dashboard/app/pages/SkillsLibrary.jsx +2 -3
  69. package/src/dashboard/app/pages/Workflows.jsx +2 -2
  70. package/src/dashboard/scanner/agents-scanner.js +30 -35
  71. package/src/lib/agents/metrics-aggregator.js +1 -1
  72. package/src/lib/agents/output-collector.js +7 -9
  73. package/src/lib/context/context-builder.js +289 -0
  74. package/src/lib/detectors/claude-config-detector.js +19 -3
  75. package/src/lib/generators/context-generator.js +20 -42
  76. package/src/lib/generators/index.js +1 -0
  77. package/src/lib/generators/mandate-generator.js +512 -0
  78. package/src/lib/generators/metadata-extractor.js +1 -1
  79. package/src/lib/generators/recap-generator.js +3 -4
  80. package/src/lib/installers/mcp-installer.js +300 -92
  81. package/src/lib/phase-chain/phase-validator.js +36 -40
  82. package/src/lib/stack/stack-profile.js +74 -91
  83. package/src/lib/tasks/task-parser.js +1 -1
  84. package/src/lib/tasks/wave-resolver.js +353 -0
  85. package/src/lib/validators/checkpoint-persistence.js +2 -2
  86. package/src/lib/validators/content/cross-phase-validator.js +281 -0
  87. package/src/lib/validators/content/index.js +1 -0
  88. package/src/lib/validators/shared/emit-validator-dispatch.js +6 -56
  89. package/src/scripts/global-install.js +2 -27
  90. package/src/utils/agents-installer.js +224 -447
  91. package/src/utils/claude-settings-manager.js +57 -15
  92. package/src/utils/file-copier.js +1 -0
  93. package/src/utils/hooks-installer.js +15 -117
  94. package/src/utils/skills-installer.js +12 -18
  95. package/bin/detect-agents.js +0 -226
  96. package/bin/task-manager.js +0 -1036
  97. package/framework/agents/README.md +0 -13
  98. package/framework/agents/ai-agents/ai-system-architect.md +0 -194
  99. package/framework/agents/ai-agents/vector-search-expert.md +0 -247
  100. package/framework/agents/architecture/architecture-expert.md +0 -98
  101. package/framework/agents/architecture/morph-spec-architect.md +0 -66
  102. package/framework/agents/architecture/packages-validator.md +0 -89
  103. package/framework/agents/architecture/security-expert.md +0 -79
  104. package/framework/agents/architecture/seo-growth-hacker.md +0 -168
  105. package/framework/agents/architecture/standards-architect.md +0 -153
  106. package/framework/agents/backend/dotnet-senior.md +0 -163
  107. package/framework/agents/backend/ef-modeler.md +0 -119
  108. package/framework/agents/backend/hangfire-orchestrator.md +0 -133
  109. package/framework/agents/backend/ms-agent-expert.md +0 -55
  110. package/framework/agents/backend/neon-expert.md +0 -379
  111. package/framework/agents/frontend/css-specialist.md +0 -89
  112. package/framework/agents/frontend/design-system-validator.md +0 -100
  113. package/framework/agents/frontend/gsap-animator.md +0 -131
  114. package/framework/agents/frontend/nextjs-component-validator.md +0 -97
  115. package/framework/agents/frontend/nextjs-expert.md +0 -201
  116. package/framework/agents/frontend/ui-designer.md +0 -259
  117. package/framework/agents/infrastructure/infra-architect.md +0 -215
  118. package/framework/agents/integrations/asaas-financial.md +0 -138
  119. package/framework/agents/integrations/neon-auth.md +0 -151
  120. package/framework/agents/integrations/resend-email.md +0 -127
  121. package/framework/hooks/claude-code/post-tool-use/agent-complete.js +0 -122
  122. package/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -363
  123. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -78
  124. package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +0 -194
  125. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -199
  126. package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +0 -55
  127. package/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -323
  128. package/framework/hooks/claude-code/session-start/post-compact-restore.js +0 -41
  129. package/framework/hooks/claude-code/session-start/resume-context.js +0 -77
  130. package/framework/hooks/claude-code/teammate-idle/teammate-idle.js +0 -90
  131. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -114
  132. package/framework/hooks/shared/compact-restore.js +0 -123
  133. package/framework/hooks/shared/dispatch-helpers.js +0 -147
  134. package/framework/hooks/shared/skill-reminder-helpers.js +0 -79
  135. package/framework/hooks/shared/stale-task-reset.js +0 -57
  136. package/framework/hooks/shared/worktree-helpers.js +0 -75
  137. package/framework/skills/level-0-meta/README.md +0 -7
  138. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +0 -472
  139. package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +0 -174
  140. package/framework/skills/level-0-meta/morph-brainstorming/references/proposal-example.md +0 -138
  141. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +0 -145
  142. package/framework/skills/level-0-meta/morph-code-review/SKILL.md +0 -250
  143. package/framework/skills/level-0-meta/morph-code-review/references/review-example.md +0 -164
  144. package/framework/skills/level-0-meta/morph-code-review/references/review-guidelines.md +0 -100
  145. package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +0 -151
  146. package/framework/skills/level-0-meta/morph-code-review-nextjs/SKILL.md +0 -165
  147. package/framework/skills/level-0-meta/morph-code-review-nextjs/references/review-example-nextjs.md +0 -254
  148. package/framework/skills/level-0-meta/morph-code-review-nextjs/scripts/scan-nextjs.mjs +0 -189
  149. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +0 -344
  150. package/framework/skills/level-0-meta/morph-frontend-review/scripts/scan-accessibility.mjs +0 -376
  151. package/framework/skills/level-0-meta/morph-gemini-image/SKILL.md +0 -290
  152. package/framework/skills/level-0-meta/morph-init/SKILL.md +0 -537
  153. package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +0 -225
  154. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +0 -401
  155. package/framework/skills/level-0-meta/morph-post-implementation/scripts/detect-dev-server.mjs +0 -153
  156. package/framework/skills/level-0-meta/morph-post-implementation/scripts/detect-stack.mjs +0 -234
  157. package/framework/skills/level-0-meta/morph-simulation-checklist/SKILL.md +0 -106
  158. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +0 -243
  159. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +0 -169
  160. package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +0 -148
  161. package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +0 -110
  162. package/framework/skills/level-1-workflows/README.md +0 -7
  163. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +0 -269
  164. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +0 -453
  165. package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +0 -44
  166. package/framework/skills/level-1-workflows/morph-phase-design/references/spec-authoring-guide.md +0 -55
  167. package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +0 -253
  168. package/framework/skills/level-1-workflows/morph-phase-implement/.morph/logs/activity.json +0 -38
  169. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +0 -634
  170. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +0 -50
  171. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +0 -54
  172. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +0 -47
  173. package/framework/skills/level-1-workflows/morph-phase-implement/references/recap-example.md +0 -132
  174. package/framework/skills/level-1-workflows/morph-phase-implement/references/vsa-implementation-guide.md +0 -92
  175. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +0 -257
  176. package/framework/skills/level-1-workflows/morph-phase-tasks/.morph/logs/activity.json +0 -14
  177. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +0 -291
  178. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +0 -143
  179. package/framework/skills/level-1-workflows/morph-phase-tasks/references/tasks-example.md +0 -404
  180. package/framework/skills/level-1-workflows/morph-phase-tasks/scripts/validate-tasks.mjs +0 -112
  181. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +0 -995
  182. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +0 -147
  183. package/framework/squad-templates/backend-only.json +0 -47
  184. package/framework/squad-templates/frontend-only.json +0 -56
  185. package/framework/squad-templates/full-stack.json +0 -74
  186. package/src/commands/agents/agent-metrics.js +0 -174
  187. package/src/commands/agents/audit-dispatch.js +0 -82
  188. package/src/commands/agents/detect-agents.js +0 -275
  189. package/src/commands/agents/dispatch-agents.js +0 -461
  190. package/src/commands/agents/index.js +0 -13
  191. package/src/commands/agents/manage-agents.js +0 -352
  192. package/src/commands/agents/project-metrics.js +0 -74
  193. package/src/commands/phase/phase-reset.js +0 -74
  194. package/src/commands/scope/escalate.js +0 -217
  195. package/src/commands/state/advance-phase.js +0 -600
  196. package/src/commands/state/phase-runner.js +0 -215
  197. package/src/commands/state/state.js +0 -444
  198. package/src/commands/task/expand.js +0 -100
  199. package/src/commands/tasks/index.js +0 -4
  200. package/src/commands/tasks/task.js +0 -105
  201. package/src/commands/templates/index.js +0 -5
  202. package/src/commands/templates/template-render.js +0 -93
  203. package/src/commands/trust/trust.js +0 -118
  204. package/src/lib/agents/agents-manager.js +0 -349
  205. package/src/lib/build/build-runner.js +0 -99
  206. package/src/lib/checkpoints/checkpoint-hooks.js +0 -111
  207. package/src/lib/contracts/sprint-contract-generator.js +0 -137
  208. package/src/lib/scope/impact-analyzer.js +0 -106
  209. package/src/lib/trust/trust-manager.js +0 -157
  210. package/src/utils/tier-helpers.js +0 -24
  211. /package/framework/hooks/claude-code/{post-tool-use → core}/loop-detect.js +0 -0
@@ -1,404 +0,0 @@
1
- # Tasks - Photo Processing Pipeline
2
-
3
- > Example of a well-structured tasks.md. This is a filled-in reference — not a template.
4
- > All tasks are atomic (15–60 min), independently commitable, and directly traceable to spec.md.
5
-
6
- | Task ID | Type | Title | Status |
7
- |---------|------|-------|--------|
8
- | T001 | Contract | Define C# contracts and interfaces | Done |
9
- | T002 | Domain | Create ProcessingJob entity and enum | Done |
10
- | T003 | Infra | EF Core migration and DbContext setup | Done |
11
- | T004 | Infra | Azure Blob Storage service | Done |
12
- | T005 | Service | Implement PhotoProcessingService | In Progress |
13
- | T006 | Job | Implement Hangfire background job | Pending |
14
- | T007 | API | Upload and status endpoints (Minimal API) | Pending |
15
- | T008 | UI | Blazor upload page component | Pending |
16
- | T009 | UI | Blazor status polling page | Pending |
17
- | T010 | Test | Unit tests for PhotoProcessingService | Pending |
18
- | T011 | Test | Integration tests for upload + status API | Pending |
19
-
20
- **Status Values:** `Pending | In Progress | Blocked | Done`
21
-
22
- ---
23
-
24
- ## Phase 1: Contracts & Data Model
25
-
26
- ### T001: Define C# contracts and interfaces
27
- - **Type:** Contract
28
- - **Priority:** 1
29
- - **Estimate:** 30min
30
- - **Assigned:** dotnet-senior
31
- - **Dependencies:** None
32
-
33
- **Description:**
34
- Define all service interfaces, command/result records, and DTOs needed for the feature. These become the API contract other tasks depend on — implement data model and services against these interfaces.
35
-
36
- **Deliverables:**
37
- - [ ] Create: `src/Application/PhotoProcessing/Interfaces/IPhotoProcessingService.cs`
38
- - [ ] Create: `src/Application/PhotoProcessing/Commands/UploadPhotoCommand.cs`
39
- - [ ] Create: `src/Application/PhotoProcessing/Queries/GetJobStatusQuery.cs`
40
- - [ ] Create: `src/Application/PhotoProcessing/DTOs/JobStatusDto.cs`
41
-
42
- ---
43
-
44
- ### T002: Create ProcessingJob entity and enum
45
- - **Type:** Domain
46
- - **Priority:** 1
47
- - **Estimate:** 30min
48
- - **Assigned:** dotnet-senior
49
- - **Dependencies:** T001
50
-
51
- **Description:**
52
- Create the `ProcessingJob` domain entity and `ProcessingStatus` enum per the data model in spec.md. Entity must use private setters and expose domain methods for state transitions (`MarkProcessing()`, `MarkCompleted()`, `MarkFailed()`).
53
-
54
- **Deliverables:**
55
- - [ ] Create: `src/Domain/Entities/ProcessingJob.cs`
56
- - [ ] Create: `src/Domain/Enums/ProcessingStatus.cs`
57
-
58
- ---
59
-
60
- ### T003: EF Core migration and DbContext setup
61
- - **Type:** Infrastructure
62
- - **Priority:** 1
63
- - **Estimate:** 45min
64
- - **Assigned:** dotnet-senior
65
- - **Dependencies:** T002
66
-
67
- **Description:**
68
- Add `ProcessingJob` to `AppDbContext`, configure via Fluent API (column lengths, indexes, defaults), and create initial migration. Verify migration applies cleanly to a local SQL Server instance.
69
-
70
- **Deliverables:**
71
- - [ ] Update: `src/Infrastructure/Persistence/AppDbContext.cs`
72
- - [ ] Create: `src/Infrastructure/Persistence/Configurations/ProcessingJobConfiguration.cs`
73
- - [ ] Run: `dotnet ef migrations add AddProcessingJob`
74
- - [ ] Verify: migration applies without errors
75
-
76
- ---
77
-
78
- ## Phase 2: Infrastructure Services
79
-
80
- ### T004: Azure Blob Storage service
81
- - **Type:** Infrastructure
82
- - **Priority:** 1
83
- - **Estimate:** 45min
84
- - **Assigned:** infra-architect
85
- - **Dependencies:** None
86
-
87
- **Description:**
88
- Implement `IBlobStorageService` with upload and generate-URL operations using `Azure.Storage.Blobs` SDK. Register as scoped in DI. Add connection string to `appsettings.json` (placeholder) and Key Vault reference for production.
89
-
90
- **Deliverables:**
91
- - [ ] Create: `src/Infrastructure/Storage/IBlobStorageService.cs`
92
- - [ ] Create: `src/Infrastructure/Storage/AzureBlobStorageService.cs`
93
- - [ ] Create: `src/Infrastructure/Storage/FakeBlobStorageService.cs` (for simulation mode)
94
- - [ ] Update: `src/Infrastructure/DependencyInjection.cs`
95
-
96
- ---
97
-
98
- ### T005: Implement PhotoProcessingService
99
- - **Type:** Service
100
- - **Priority:** 2
101
- - **Estimate:** 1h
102
- - **Assigned:** dotnet-senior
103
- - **Dependencies:** T001, T002, T003, T004
104
-
105
- **Description:**
106
- Implement `IPhotoProcessingService` with `UploadAsync` (validate → blob upload → create job → enqueue Hangfire job) and `GetStatusAsync`. Use result pattern for validation errors; throw `NotFoundException` for missing jobs.
107
-
108
- **Deliverables:**
109
- - [ ] Create: `src/Application/PhotoProcessing/PhotoProcessingService.cs`
110
- - [ ] Update: `src/Application/DependencyInjection.cs`
111
-
112
- ---
113
-
114
- ### T006: Implement Hangfire background job
115
- - **Type:** Job
116
- - **Priority:** 2
117
- - **Estimate:** 1h
118
- - **Assigned:** dotnet-senior
119
- - **Dependencies:** T002, T004
120
-
121
- **Description:**
122
- Implement `IPhotoProcessingJob` that: sets status = Processing → downloads original from Blob → calls AI API → uploads processed photo → sets status = Completed. On exception: increment RetryCount, set Failed if >= 3. Add `[AutomaticRetry(Attempts = 3)]` attribute.
123
-
124
- **Deliverables:**
125
- - [ ] Create: `src/Application/PhotoProcessing/PhotoProcessingJob.cs`
126
- - [ ] Create: `src/Application/PhotoProcessing/FakePhotoProcessingJob.cs` (simulation mode)
127
-
128
- ---
129
-
130
- ## Phase 3: API Endpoints
131
-
132
- ### T007: Upload and status endpoints (Minimal API)
133
- - **Type:** API
134
- - **Priority:** 2
135
- - **Estimate:** 45min
136
- - **Assigned:** dotnet-senior
137
- - **Dependencies:** T005
138
-
139
- **Description:**
140
- Create two endpoints per spec.md:
141
- - `POST /api/upload` — multipart/form-data, returns `{ jobId }`, maps to `UploadPhotoCommand`
142
- - `GET /api/status/{jobId}` — returns `JobStatusDto`
143
- - `GET /api/download/{jobId}` — redirects to Blob URL if Completed, else 404
144
-
145
- **Deliverables:**
146
- - [ ] Create: `src/Web/Endpoints/PhotoProcessingEndpoints.cs`
147
- - [ ] Update: `src/Web/Program.cs` to register endpoint group
148
-
149
- ---
150
-
151
- ## Phase 4: UI Components
152
-
153
- ### T008: Blazor upload page component
154
- - **Type:** UI
155
- - **Priority:** 2
156
- - **Estimate:** 1h
157
- - **Assigned:** nextjs-expert
158
- - **Dependencies:** T007
159
-
160
- **Description:**
161
- Frontend page at `/upload`. File input with client-side validation (type + size before submit). Loading state during upload. Redirect to `/processing/{jobId}` on success. Error message display per spec wireframe.
162
-
163
- **Deliverables:**
164
- - [ ] Create: `src/Web/Pages/Upload.razor`
165
- - [ ] Create: `src/Web/Pages/Upload.razor.cs`
166
-
167
- ---
168
-
169
- ### T009: Blazor status polling page
170
- - **Type:** UI
171
- - **Priority:** 3
172
- - **Estimate:** 1h
173
- - **Assigned:** nextjs-expert
174
- - **Dependencies:** T007
175
-
176
- **Description:**
177
- Frontend page at `/processing/{jobId}`. Polls `GET /api/status/{jobId}` every 5 seconds using `PeriodicTimer`. Shows status label + progress indicator. "Download" button when Completed. "Retry" suggestion when Failed. Stops polling on terminal state.
178
-
179
- **Deliverables:**
180
- - [ ] Create: `src/Web/Pages/ProcessingStatus.razor`
181
- - [ ] Create: `src/Web/Pages/ProcessingStatus.razor.cs`
182
-
183
- ---
184
-
185
- ## Phase 5: Tests
186
-
187
- ### T010: Unit tests for PhotoProcessingService
188
- - **Type:** Test
189
- - **Priority:** 2
190
- - **Estimate:** 1h
191
- - **Assigned:** dotnet-senior
192
- - **Dependencies:** T005
193
-
194
- **Description:**
195
- Unit tests covering: happy path upload, invalid file type rejection, file too large rejection, status retrieval for each status value, not-found case. Use Moq for `IBlobStorageService` and `IProcessingJobRepository`. FluentAssertions for assertions.
196
-
197
- **Deliverables:**
198
- - [ ] Create: `tests/Unit/Application/PhotoProcessing/PhotoProcessingServiceTests.cs`
199
-
200
- ---
201
-
202
- ### T011: Integration tests for upload + status API
203
- - **Type:** Test
204
- - **Priority:** 3
205
- - **Estimate:** 1h
206
- - **Assigned:** dotnet-senior
207
- - **Dependencies:** T007, T010
208
-
209
- **Description:**
210
- Integration tests using `WebApplicationFactory` + in-memory SQLite (or TestContainers for SQL Server). Tests: POST /api/upload returns 200 with jobId, GET /api/status/{jobId} returns correct status, GET /api/download/{completedJobId} returns redirect.
211
-
212
- **Deliverables:**
213
- - [ ] Create: `tests/Integration/Api/PhotoProcessingEndpointTests.cs`
214
- - [ ] Create: `tests/Integration/Fixtures/PhotoProcessingApiFixture.cs`
215
-
216
- ---
217
-
218
- ## Summary
219
-
220
- | Phase | Tasks | Estimate |
221
- |-------|-------|----------|
222
- | Contracts & Data Model | T001–T003 | 1h45m |
223
- | Infrastructure Services | T004–T006 | 2h45m |
224
- | API Endpoints | T007 | 45m |
225
- | UI Components | T008–T009 | 2h |
226
- | Tests | T010–T011 | 2h |
227
- | **Total** | **11 tasks** | **~9h15m** |
228
-
229
- ---
230
-
231
- ---
232
-
233
- # Tasks - Book CRUD (VSA Example)
234
-
235
- > Example of tasks.md for a Vertical Slice Architecture (VSA) feature.
236
- > Key rule: 1 task = 1 complete slice (Handler + Validator + Endpoint together).
237
- > GetAll slices have no Validator — stated explicitly in the task.
238
-
239
- | Task ID | Category | Title | Status |
240
- |---------|----------|-------|--------|
241
- | T001 | entity | Criar Entity Book + registrar DbSet no ApplicationDbContext | Pending |
242
- | T002 | errors | Criar BookErrors (NotFound + outros factory methods) | Pending |
243
- | T003 | tags | Adicionar ApiTags.Books em Constants/ApiTags.cs | Pending |
244
- | T004 | migration | Criar migration AddBook + aplicar ao banco | Pending |
245
- | T005 | slice | Implementar slice CreateBook (Handler + Validator + Endpoint) | Pending |
246
- | T006 | slice | Implementar slice GetAllBooks (Handler + Endpoint, sem Validator) | Pending |
247
- | T007 | slice | Implementar slice GetBookById (Handler + Validator + Endpoint) | Pending |
248
- | T008 | slice | Implementar slice UpdateBook (Handler + Validator + Endpoint) | Pending |
249
- | T009 | slice | Implementar slice DeleteBook (Handler + Validator + Endpoint) | Pending |
250
-
251
- **Status Values:** `Pending | In Progress | Blocked | Done`
252
-
253
- ---
254
-
255
- ## Phase 1: Foundation
256
-
257
- ### T001: Criar Entity Book + registrar DbSet no ApplicationDbContext
258
- - **Category:** entity
259
- - **Estimate:** 20min
260
- - **Dependencies:** None
261
-
262
- **Description:**
263
- Criar a entity `Book` com todos os campos definidos no spec.md. Registrar `DbSet<Book>` no `ApplicationDbContext`. Usar `Guid.CreateVersion7()` para o campo Id — não `Guid.NewGuid()`. Propriedades obrigatórias como `sealed` ou com setters `private init`.
264
-
265
- **Deliverables:**
266
- - [ ] Create: `Entities/Book.cs`
267
- - [ ] Update: `Database/ApplicationDbContext.cs` (add `public DbSet<Book> Books { get; set; } = null!;`)
268
-
269
- ---
270
-
271
- ### T002: Criar BookErrors (NotFound + outros factory methods)
272
- - **Category:** errors
273
- - **Estimate:** 10min
274
- - **Dependencies:** T001
275
-
276
- **Description:**
277
- Criar a classe `BookErrors` static com factory methods para cada tipo de erro da feature. Cada method retorna um `Error` com code e description. Esses erros são compartilhados por todos os slices da BookFeature.
278
-
279
- **Deliverables:**
280
- - [ ] Create: `Features/BookFeature/BookErrors.cs`
281
-
282
- ---
283
-
284
- ### T003: Adicionar ApiTags.Books em Constants/ApiTags.cs
285
- - **Category:** tags
286
- - **Estimate:** 5min
287
- - **Dependencies:** None
288
-
289
- **Description:**
290
- Adicionar a constante `Books` em `ApiTags` para uso em todos os endpoints da feature. Se a constante já existir, pular esta task.
291
-
292
- **Deliverables:**
293
- - [ ] Update: `Constants/ApiTags.cs` (add `public const string Books = "books";`)
294
-
295
- ---
296
-
297
- ### T004: Criar migration AddBook + aplicar ao banco
298
- - **Category:** migration
299
- - **Estimate:** 10min
300
- - **Dependencies:** T001
301
-
302
- **Description:**
303
- Gerar a migration EF Core para a entity `Book` e aplicar ao banco local. Verificar que a migration foi gerada corretamente antes de aplicar.
304
-
305
- **Deliverables:**
306
- - [ ] Run: `dotnet ef migrations add AddBook`
307
- - [ ] Run: `dotnet ef database update`
308
- - [ ] Verify: migration applies without errors
309
-
310
- ---
311
-
312
- ## Phase 2: Slices
313
-
314
- ### T005: Implementar slice CreateBook (Handler + Validator + Endpoint)
315
- - **Category:** slice
316
- - **Estimate:** 45min
317
- - **Dependencies:** T001, T002, T003, T004
318
-
319
- **Description:**
320
- Implementar o slice completo de criação. O arquivo Handler deve conter os records `CreateBookRequest` e `CreateBookResponse` no mesmo arquivo. O Validator deve herdar de `AbstractValidator<CreateBookRequest>`. O Endpoint deve ser `internal sealed` e usar `result.Match()` — nunca `result.Value` sem checar `IsSuccess`.
321
-
322
- Handler injeta: `IRepository<Book>` + `IUnitOfWork`.
323
-
324
- **Deliverables:**
325
- - [ ] Create: `Features/BookFeature/CreateBook/CreateBookHandler.cs`
326
- - [ ] Create: `Features/BookFeature/CreateBook/CreateBookValidator.cs`
327
- - [ ] Create: `Features/BookFeature/CreateBook/CreateBookEndpoint.cs`
328
-
329
- ---
330
-
331
- ### T006: Implementar slice GetAllBooks (Handler + Endpoint, sem Validator)
332
- - **Category:** slice
333
- - **Estimate:** 25min
334
- - **Dependencies:** T001, T004
335
-
336
- **Description:**
337
- Implementar o slice de listagem. GetAll NÃO tem Validator (sem parâmetros de entrada para validar). Handler injeta apenas `IRepository<Book>` — não precisa de `IUnitOfWork` (read-only).
338
-
339
- **Deliverables:**
340
- - [ ] Create: `Features/BookFeature/GetAllBooks/GetAllBooksHandler.cs`
341
- - [ ] Create: `Features/BookFeature/GetAllBooks/GetAllBooksEndpoint.cs`
342
-
343
- ---
344
-
345
- ### T007: Implementar slice GetBookById (Handler + Validator + Endpoint)
346
- - **Category:** slice
347
- - **Estimate:** 30min
348
- - **Dependencies:** T001, T002, T004
349
-
350
- **Description:**
351
- Implementar o slice de busca por ID. Validator verifica que o Guid não é empty. Handler retorna `BookErrors.NotFound()` se o livro não existir. Handler injeta apenas `IRepository<Book>`.
352
-
353
- **Deliverables:**
354
- - [ ] Create: `Features/BookFeature/GetBookById/GetBookByIdHandler.cs`
355
- - [ ] Create: `Features/BookFeature/GetBookById/GetBookByIdValidator.cs`
356
- - [ ] Create: `Features/BookFeature/GetBookById/GetBookByIdEndpoint.cs`
357
-
358
- ---
359
-
360
- ### T008: Implementar slice UpdateBook (Handler + Validator + Endpoint)
361
- - **Category:** slice
362
- - **Estimate:** 45min
363
- - **Dependencies:** T001, T002, T003, T004
364
-
365
- **Description:**
366
- Implementar o slice de atualização. Handler retorna `BookErrors.NotFound()` se o livro não existir antes de atualizar. Handler injeta: `IRepository<Book>` + `IUnitOfWork`.
367
-
368
- **Deliverables:**
369
- - [ ] Create: `Features/BookFeature/UpdateBook/UpdateBookHandler.cs`
370
- - [ ] Create: `Features/BookFeature/UpdateBook/UpdateBookValidator.cs`
371
- - [ ] Create: `Features/BookFeature/UpdateBook/UpdateBookEndpoint.cs`
372
-
373
- ---
374
-
375
- ### T009: Implementar slice DeleteBook (Handler + Validator + Endpoint)
376
- - **Category:** slice
377
- - **Estimate:** 30min
378
- - **Dependencies:** T001, T002, T003, T004
379
-
380
- **Description:**
381
- Implementar o slice de deleção. Handler verifica existência antes de deletar, retorna `BookErrors.NotFound()` se não existir. Handler injeta: `IRepository<Book>` + `IUnitOfWork`.
382
-
383
- **Deliverables:**
384
- - [ ] Create: `Features/BookFeature/DeleteBook/DeleteBookHandler.cs`
385
- - [ ] Create: `Features/BookFeature/DeleteBook/DeleteBookValidator.cs`
386
- - [ ] Create: `Features/BookFeature/DeleteBook/DeleteBookEndpoint.cs`
387
-
388
- ---
389
-
390
- ## Summary
391
-
392
- | Phase | Tasks | Estimate |
393
- |-------|-------|----------|
394
- | Foundation (entity + errors + tags + migration) | T001–T004 | 45min |
395
- | Slices (Create + GetAll + GetById + Update + Delete) | T005–T009 | 2h55m |
396
- | **Total** | **9 tasks** | **~3h40m** |
397
-
398
- > **VSA Note:** No manual DI registration needed — `AddHandlersFromAssembly()`,
399
- > `RegisterApiEndpointsFromAssembly()`, and `AddValidatorsFromAssembly()` discover
400
- > all handlers, endpoints and validators automatically via assembly scanning (Scrutor).
401
-
402
- ---
403
-
404
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,112 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * validate-tasks.mjs
4
- *
5
- * Validates a MORPH-SPEC tasks.md file for structure and completeness.
6
- * Executed locally by Claude via Bash — output returned to Claude.
7
- *
8
- * Usage:
9
- * node validate-tasks.mjs <tasks-file>
10
- * node validate-tasks.mjs .morph/features/my-feature/4-tasks/tasks.md
11
- *
12
- * Checks:
13
- * - Summary table exists with T### IDs and valid statuses
14
- * - Each task header has T### format
15
- * - Each task has Type, Priority, Estimate, Dependencies fields
16
- * - Each task has at least one deliverable checkbox
17
- * - Task IDs are sequential (no gaps)
18
- * - Reports counts by status
19
- */
20
-
21
- import { readFileSync, existsSync } from 'fs';
22
-
23
- const taskFile = process.argv[2];
24
-
25
- if (!taskFile) {
26
- console.error(JSON.stringify({ error: 'Usage: validate-tasks.mjs <tasks-file>' }));
27
- process.exit(1);
28
- }
29
-
30
- if (!existsSync(taskFile)) {
31
- console.error(JSON.stringify({ error: `File not found: ${taskFile}` }));
32
- process.exit(1);
33
- }
34
-
35
- const content = readFileSync(taskFile, 'utf-8');
36
- const lines = content.split('\n');
37
-
38
- const errors = [];
39
- const warnings = [];
40
-
41
- // 1. Parse summary table (| T001 | Type | Title | Status |)
42
- const tableRows = lines.filter(l => /^\|\s*T\d{3}/.test(l));
43
- const VALID_STATUSES = new Set(['Pending', 'In Progress', 'Blocked', 'Done']);
44
- const summaryTasks = [];
45
-
46
- for (const row of tableRows) {
47
- const parts = row.split('|').map(s => s.trim()).filter(Boolean);
48
- if (parts.length < 4) continue;
49
- const [id, , , status] = parts;
50
- summaryTasks.push({ id, status });
51
- if (!VALID_STATUSES.has(status)) {
52
- errors.push(`Task ${id}: invalid status '${status}' — must be one of: ${[...VALID_STATUSES].join(', ')}`);
53
- }
54
- }
55
-
56
- if (summaryTasks.length === 0) {
57
- errors.push('No summary table found — expected rows matching | T### | Type | Title | Status |');
58
- }
59
-
60
- // 2. Parse task headers (### T001: Title or ### T001 — Title or ### T001 - Title)
61
- const taskHeaders = lines
62
- .map((l, i) => ({ line: i + 1, match: l.match(/^###\s+(T\d{3})\s*[—–:\-]\s+(.+)/) }))
63
- .filter(r => r.match);
64
-
65
- // Check sequential IDs
66
- const ids = taskHeaders.map(r => parseInt(r.match[1].slice(1)));
67
- for (let i = 0; i < ids.length; i++) {
68
- if (ids[i] !== i + 1) {
69
- warnings.push(`Task ID gap or duplicate near T${String(ids[i]).padStart(3, '0')} (expected T${String(i + 1).padStart(3, '0')})`);
70
- break;
71
- }
72
- }
73
-
74
- // 3. Check each task section has required fields
75
- for (const { line, match } of taskHeaders) {
76
- const taskId = match[1];
77
- // Collect lines in this task section (until next ### or end)
78
- const start = line; // 1-indexed
79
- let end = lines.length;
80
- for (let i = start; i < lines.length; i++) {
81
- if (i > start - 1 && /^#{1,3}\s/.test(lines[i])) { end = i; break; }
82
- }
83
- const section = lines.slice(start, end).join('\n');
84
-
85
- if (!/\*\*Type:\*\*/.test(section)) errors.push(`${taskId}: missing **Type:** field`);
86
- if (!/\*\*Priority:\*\*/.test(section)) errors.push(`${taskId}: missing **Priority:** field`);
87
- if (!/\*\*Estimate:\*\*/.test(section)) errors.push(`${taskId}: missing **Estimate:** field`);
88
- if (!/\*\*Dependencies:\*\*/.test(section)) warnings.push(`${taskId}: missing **Dependencies:** field`);
89
- if (!/- \[ \]/.test(section)) warnings.push(`${taskId}: no deliverable checkboxes found`);
90
- }
91
-
92
- // 4. Status counts
93
- const statusCounts = {};
94
- for (const { status } of summaryTasks) {
95
- statusCounts[status] = (statusCounts[status] ?? 0) + 1;
96
- }
97
-
98
- const result = {
99
- file: taskFile,
100
- valid: errors.length === 0,
101
- tasks: {
102
- total: summaryTasks.length,
103
- byStatus: statusCounts,
104
- completed: statusCounts['Done'] ?? 0,
105
- remaining: (summaryTasks.length) - (statusCounts['Done'] ?? 0),
106
- },
107
- errors,
108
- warnings,
109
- };
110
-
111
- console.log(JSON.stringify(result, null, 2));
112
- process.exit(errors.length > 0 ? 1 : 0);