@polymorphism-tech/morph-spec 4.22.0 → 6.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 (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,250 +0,0 @@
1
- ---
2
- name: morph-code-review
3
- description: .NET/C# code review checklist covering naming conventions, architecture layer integrity, async patterns, logging, error handling, DI lifetimes, and DTO contracts. Use after implementing .NET code, before creating PRs, or when reviewing C# code for compliance with MORPH-SPEC standards.
4
- user-invocable: true
5
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep
6
- stacks:
7
- - dotnet
8
- ---
9
-
10
- # Code Review Checklist
11
-
12
- > Comprehensive checklist for .NET code review: naming, architecture, clean code, duplication, and runtime patterns.
13
- > **Example:** `references/review-example.md` — filled-in review showing expected finding format and severity levels.
14
- > **Script:** `scripts/scan-csharp.mjs` — automated scan for CRITICAL/HIGH violations before manual review.
15
- > **Ref:** `references/review-guidelines.md` — false-positive rubric, confidence scoring, evidence format.
16
-
17
- ---
18
-
19
- ## Step 0 — Eligibility Check
20
-
21
- ```bash
22
- git diff --name-only main...HEAD -- "*.cs" | wc -l
23
- ```
24
-
25
- **Skip review if:**
26
- - 0 `.cs` files changed → no backend code to review
27
- - Only changes in `*.json`, `*.csproj`, `*.md`, migration files → infrastructure scope
28
- - `.morph/features/$ARGUMENTS/5-implement/code-review.md` already exists from today → already reviewed
29
-
30
- If skipping: output `"Skipping code-review: [reason]"` and stop.
31
-
32
- ---
33
-
34
- ## Naming & Style (ref: coding.md)
35
-
36
- - [ ] `[CRITICAL]` Constants use PascalCase (`MaxRetryCount`, NOT `MAX_RETRY_COUNT`)
37
- - [ ] `[CRITICAL]` No Hungarian notation (`strName`, `iCount`, `btnSubmit`)
38
- - [ ] `[HIGH]` Private fields use `_camelCase` prefix
39
- - [ ] `[HIGH]` Async methods have `Async` suffix
40
- - [ ] `[HIGH]` Interfaces prefixed with `I`
41
- - [ ] `[MEDIUM]` No abbreviations in public APIs (`repository` not `repo`)
42
- - [ ] `[MEDIUM]` All classes `sealed` unless designed for inheritance
43
- - [ ] `[MEDIUM]` File-scoped namespaces used
44
-
45
- ---
46
-
47
- ## Architecture Review (ref: architecture.md)
48
-
49
- ### Layer Integrity
50
- - [ ] `[CRITICAL]` Domain has zero references to Infrastructure or Web
51
- - [ ] `[CRITICAL]` No circular dependencies between projects
52
- - [ ] `[HIGH]` Application does NOT reference Web project
53
- - [ ] `[HIGH]` Infrastructure details don't leak into Application DTOs
54
-
55
- ### Responsibility & Organization
56
- - [ ] `[HIGH]` No class > 300 lines (SRP violation)
57
- - [ ] `[HIGH]` Controllers/pages are thin (< 50 lines logic)
58
- - [ ] `[MEDIUM]` One class per file, file name = class name
59
- - [ ] `[MEDIUM]` Files in correct project/folder per architecture.md
60
- - [ ] `[LOW]` No "God classes" (10+ constructor dependencies)
61
-
62
- ### Dependencies
63
- - [ ] `[HIGH]` External services accessed through interfaces
64
- - [ ] `[HIGH]` No hardcoded connection strings, URLs, or secrets
65
- - [ ] `[MEDIUM]` Configuration via Options pattern (`IOptions<T>`)
66
- - [ ] `[LOW]` No over-abstraction (interface with 1 impl never mocked)
67
-
68
- ---
69
-
70
- ## Clean Code Review
71
-
72
- ### Method Quality
73
- - [ ] `[HIGH]` No methods > 30 lines (extract sub-methods)
74
- - [ ] `[HIGH]` No methods with > 4 parameters (use request object)
75
- - [ ] `[MEDIUM]` No nested conditionals > 3 levels (use early return)
76
- - [ ] `[MEDIUM]` No complex conditionals (> 3 conditions — extract to named method)
77
-
78
- ### Magic Values
79
- - [ ] `[HIGH]` No magic strings in comparisons (use enum or constant)
80
- - [ ] `[HIGH]` No magic numbers (extract to PascalCase constant)
81
- - [ ] `[MEDIUM]` No hardcoded URLs, file paths, or config values
82
-
83
- ### Dead Code
84
- - [ ] `[MEDIUM]` No unused private methods
85
- - [ ] `[MEDIUM]` No unused parameters
86
- - [ ] `[LOW]` No commented-out code blocks (> 3 lines)
87
- - [ ] `[LOW]` No empty or near-empty files
88
-
89
- ---
90
-
91
- ## Duplication Review
92
-
93
- - [ ] `[HIGH]` No exact/near-exact duplicate methods across classes
94
- - [ ] `[HIGH]` No duplicate model definitions (same properties in different classes)
95
- - [ ] `[MEDIUM]` No thin wrappers that only delegate without adding value
96
- - [ ] `[MEDIUM]` No mirrored interface methods (extract base interface)
97
- - [ ] `[MEDIUM]` No duplicate enums across projects (centralize in Domain)
98
- - [ ] `[LOW]` No passthrough service methods (controller -> service with zero logic)
99
-
100
- ---
101
-
102
- ## Async & Cancellation
103
-
104
- - [ ] `[CRITICAL]` CancellationToken propagated through entire call chain
105
- - [ ] `[CRITICAL]` No `.Result` or `.Wait()` (deadlock risk in ASP.NET)
106
- - [ ] `[HIGH]` No `async void` (except event handlers)
107
- - [ ] `[HIGH]` Timeout configured for external operations
108
- - [ ] `[MEDIUM]` `ConfigureAwait(false)` only in library code
109
-
110
- ---
111
-
112
- ## Logging
113
-
114
- - [ ] `[HIGH]` Logs at critical points (entry, exit, errors)
115
- - [ ] `[HIGH]` No `$""` string interpolation in log methods (use message templates)
116
- - [ ] `[HIGH]` No sensitive data logged (passwords, tokens, PII)
117
- - [ ] `[MEDIUM]` Logs include correlation IDs (OrderId, UserId)
118
- - [ ] `[MEDIUM]` Appropriate log level (Information, Warning, Error)
119
-
120
- ---
121
-
122
- ## Error Handling
123
-
124
- - [ ] `[CRITICAL]` No empty catch blocks
125
- - [ ] `[HIGH]` Specific exceptions (not generic `catch (Exception)` without re-throw)
126
- - [ ] `[HIGH]` Inner exception preserved on re-throw
127
- - [ ] `[HIGH]` Result pattern for expected business errors, exceptions for infrastructure
128
- - [ ] `[MEDIUM]` Consistent error handling pattern across all services
129
-
130
- ---
131
-
132
- ## DI
133
-
134
- - [ ] `[HIGH]` Constructor injection with interfaces (not concrete types)
135
- - [ ] `[HIGH]` Correct lifetime (Scoped for DbContext, Singleton for factories)
136
- - [ ] `[MEDIUM]` No service locator pattern (`IServiceProvider.GetService<T>()` in business code)
137
-
138
- ---
139
-
140
- ## Services
141
-
142
- ### State Validation
143
- - [ ] `[HIGH]` Validates INVALID states (not valid ones) for future extensibility
144
- - [ ] `[HIGH]` Error states handled explicitly
145
-
146
- ```csharp
147
- // Correct: validate INVALID states
148
- if (order.Status >= OrderStatus.Completed || order.Status == OrderStatus.Failed)
149
- throw new InvalidOperationException("Cannot process completed or failed order");
150
- ```
151
-
152
- ### Transactions
153
- - [ ] `[HIGH]` Multiple operations wrapped in transaction
154
- - [ ] `[HIGH]` Rollback on error
155
-
156
- ```csharp
157
- await using var transaction = await _context.Database.BeginTransactionAsync(ct);
158
- try
159
- {
160
- await _repository.AddAsync(order, ct);
161
- await _paymentService.ChargeAsync(order.Id, ct);
162
- await transaction.CommitAsync(ct);
163
- }
164
- catch { await transaction.RollbackAsync(ct); throw; }
165
- ```
166
-
167
- ---
168
-
169
- ## Background Operations
170
-
171
- ### DbContext Safety
172
- - [ ] `[CRITICAL]` Uses `IDbContextFactory` (not scoped DbContext)
173
- - [ ] `[CRITICAL]` Repository created via Factory with `await using`
174
- - [ ] `[HIGH]` No `Task.Delay` as race condition workaround
175
-
176
- ```csharp
177
- // Correct pattern
178
- _ = Task.Run(async () =>
179
- {
180
- try
181
- {
182
- await using var repo = _repoFactory.CreateScoped();
183
- var order = await repo.GetByIdAsync(orderId);
184
- // ...
185
- }
186
- catch (Exception ex) { _logger.LogError(ex, "Failed {OrderId}", orderId); }
187
- });
188
- ```
189
-
190
- ### Hangfire Jobs
191
- - [ ] `[HIGH]` `[AutomaticRetry]` configured
192
- - [ ] `[HIGH]` Job is idempotent (safe to run multiple times)
193
- - [ ] `[MEDIUM]` CancellationToken used
194
- - [ ] `[MEDIUM]` No HTTP request state dependency
195
-
196
- ### Resilience
197
- - [ ] `[MEDIUM]` Retry policy for transient operations
198
- - [ ] `[MEDIUM]` State persisted before long operation
199
- - [ ] `[MEDIUM]` Idempotency guaranteed for retries
200
-
201
- ---
202
-
203
- ## DTOs / Contracts
204
-
205
- ### Naming
206
- - [ ] `[HIGH]` Descriptive property names (not "Data", "Value", "Info")
207
- - [ ] `[HIGH]` Correct suffix: `Request` (input), `Response` (output), `Dto` (generic), `Command`/`Query` (CQRS)
208
-
209
- ### Types
210
- - [ ] `[MEDIUM]` `Stream` for large files, `byte[]` for small in-memory data
211
- - [ ] `[MEDIUM]` `DateTimeOffset` for timestamps, `DateTime` for local dates
212
- - [ ] `[MEDIUM]` Nullable `?` only where truly optional
213
-
214
- ### Structure
215
- - [ ] `[MEDIUM]` Records for immutable DTOs, classes with `init` for mutable entities
216
- - [ ] `[MEDIUM]` Response DTOs have all properties needed by UI
217
- - [ ] `[MEDIUM]` Enums have explicit values with logical ordering (errors at 100+)
218
-
219
- ```csharp
220
- public enum OrderStatus
221
- {
222
- Created = 0, PendingPayment = 1, Processing = 2, Completed = 3, // Normal flow
223
- Failed = 100, Cancelled = 101, Refunded = 102 // Error states
224
- }
225
- ```
226
-
227
- ### Service Interfaces
228
- - [ ] `[HIGH]` Async methods with `Async` suffix
229
- - [ ] `[HIGH]` CancellationToken as last parameter
230
- - [ ] `[MEDIUM]` `Task<Result<T>>` for expected business errors
231
-
232
- ---
233
-
234
- ## Quick Pre-Merge Checklist
235
-
236
- ```
237
- [ ] Naming follows coding.md (PascalCase constants, _camelCase fields, sealed classes)
238
- [ ] CancellationToken propagated on all async methods
239
- [ ] Structured logging at critical points (message templates, not $"")
240
- [ ] No empty catch blocks, Result pattern for business errors
241
- [ ] Background ops use IDbContextFactory + await using
242
- [ ] No duplicate code, no magic values, no methods > 30 lines
243
- [ ] Architecture layers respected (Domain has zero external refs)
244
- [ ] DTOs have descriptive names + correct types
245
- ```
246
-
247
- ---
248
-
249
- *Consolidated from: code-review-services.md + code-review-background.md + code-review-contracts.md + architecture/clean-code/duplication analysis.*
250
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,164 +0,0 @@
1
- # Code Review Report — Photo Processing Pipeline
2
-
3
- > Example of a well-structured code review output. Filled-in reference — not a template.
4
-
5
- **Scope:** `src/Application/PhotoProcessing/` + `src/Web/Endpoints/PhotoProcessingEndpoints.cs`
6
- **Date:** 2025-01-22
7
- **Reviewer:** code-review skill
8
-
9
- ---
10
-
11
- ## Findings by Severity
12
-
13
- | Severity | Count |
14
- |----------|-------|
15
- | CRITICAL | 1 |
16
- | HIGH | 2 |
17
- | MEDIUM | 2 |
18
- | LOW | 1 |
19
-
20
- ---
21
-
22
- ### [CRITICAL] Naming: UPPER_SNAKE_CASE constant
23
-
24
- **File:** `src/Application/PhotoProcessing/PhotoProcessingService.cs:14`
25
-
26
- **Current code:**
27
- ```csharp
28
- private const int MAX_RETRY_COUNT = 3;
29
- private const int DEFAULT_TIMEOUT_SECONDS = 30;
30
- ```
31
-
32
- **Suggested fix:**
33
- ```csharp
34
- private const int MaxRetryCount = 3;
35
- private const int DefaultTimeoutSeconds = 30;
36
- ```
37
-
38
- **Why:** `ALL_CAPS` constants violate C# conventions (§ coding.md). Pascal case is the .NET standard.
39
-
40
- ---
41
-
42
- ### [HIGH] Async: Missing CancellationToken propagation
43
-
44
- **File:** `src/Infrastructure/Storage/AzureBlobStorageService.cs:28`
45
-
46
- **Current code:**
47
- ```csharp
48
- public async Task<string> UploadAsync(Stream content, string blobName)
49
- {
50
- var blobClient = _containerClient.GetBlobClient(blobName);
51
- await blobClient.UploadAsync(content); // no CT
52
- return blobClient.Uri.ToString();
53
- }
54
- ```
55
-
56
- **Suggested fix:**
57
- ```csharp
58
- public async Task<string> UploadAsync(Stream content, string blobName, CancellationToken ct = default)
59
- {
60
- var blobClient = _containerClient.GetBlobClient(blobName);
61
- await blobClient.UploadAsync(content, cancellationToken: ct);
62
- return blobClient.Uri.ToString();
63
- }
64
- ```
65
-
66
- **Why:** Cancellation cannot propagate into the Blob SDK call, meaning a cancelled HTTP request still holds the upload open.
67
-
68
- ---
69
-
70
- ### [HIGH] Logging: String interpolation in ILogger call
71
-
72
- **File:** `src/Application/PhotoProcessing/PhotoProcessingJob.cs:52`
73
-
74
- **Current code:**
75
- ```csharp
76
- _logger.LogError($"Job {jobId} failed after {retryCount} retries: {ex.Message}");
77
- ```
78
-
79
- **Suggested fix:**
80
- ```csharp
81
- _logger.LogError("Job {JobId} failed after {RetryCount} retries: {ErrorMessage}",
82
- jobId, retryCount, ex.Message);
83
- ```
84
-
85
- **Why:** String interpolation allocates eagerly even if the log level is filtered. Message templates are structured and queryable in Application Insights / Seq.
86
-
87
- ---
88
-
89
- ### [MEDIUM] Architecture: Controller logic exceeds 50 lines
90
-
91
- **File:** `src/Web/Endpoints/PhotoProcessingEndpoints.cs`
92
-
93
- **Issue:** The upload endpoint inline lambda is 60+ lines — includes validation, service call, response mapping, and error handling all inline.
94
-
95
- **Suggested fix:** Extract a `UploadPhotoRequestHandler` or move validation to a FluentValidation `IValidator<UploadPhotoCommand>`. The endpoint lambda should be < 10 lines.
96
-
97
- **Why:** Fat endpoints are hard to test and violate the "thin API layer" rule (§ architecture.md).
98
-
99
- ---
100
-
101
- ### [MEDIUM] Error Handling: Generic catch without context
102
-
103
- **File:** `src/Application/PhotoProcessing/PhotoProcessingService.cs:89`
104
-
105
- **Current code:**
106
- ```csharp
107
- catch (Exception ex)
108
- {
109
- _logger.LogError(ex, "Upload failed");
110
- throw;
111
- }
112
- ```
113
-
114
- **Suggested fix:**
115
- ```csharp
116
- catch (Exception ex)
117
- {
118
- _logger.LogError(ex, "Upload failed for user {UserId}", userId);
119
- throw;
120
- }
121
- ```
122
-
123
- **Why:** Log entries without correlation IDs (UserId, JobId) are unqueryable in production. Always include the relevant entity ID.
124
-
125
- ---
126
-
127
- ### [LOW] Dead Code: Unused private method
128
-
129
- **File:** `src/Application/PhotoProcessing/PhotoProcessingService.cs:110`
130
-
131
- **Current code:**
132
- ```csharp
133
- private string BuildBlobPath(Guid jobId, string suffix)
134
- => $"uploads/{jobId}/{suffix}";
135
- // Called 0 times — path built inline everywhere
136
- ```
137
-
138
- **Suggested fix:** Either use `BuildBlobPath` consistently or delete it.
139
-
140
- **Why:** Dead code misleads future readers and increases maintenance surface.
141
-
142
- ---
143
-
144
- ## Top Priorities
145
-
146
- 1. `PhotoProcessingService.cs:14` — CRITICAL naming violation (5 min fix)
147
- 2. `AzureBlobStorageService.cs:28` — HIGH missing CancellationToken (10 min fix)
148
- 3. `PhotoProcessingJob.cs:52` — HIGH structured logging (5 min fix)
149
- 4. `PhotoProcessingEndpoints.cs` — MEDIUM endpoint refactor (30 min)
150
-
151
- ---
152
-
153
- ## Passed Checks ✅
154
-
155
- - Layer integrity: Domain has no Infrastructure references
156
- - All async methods have `Async` suffix
157
- - Private fields use `_camelCase`
158
- - No hardcoded connection strings or secrets
159
- - External services accessed through interfaces (`IBlobStorageService`, `IPhotoProcessingJob`)
160
- - `ProcessingJob` entity uses private setters + domain methods
161
-
162
- ---
163
-
164
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,100 +0,0 @@
1
- # Review Guidelines — False-Positive Rubric
2
-
3
- > Documento de referência compartilhado por todos os review skills.
4
- > Claude deve ler este documento antes de executar qualquer revisão de código.
5
-
6
- ---
7
-
8
- ## Confidence Scoring
9
-
10
- Antes de reportar um finding, atribua um confidence score de 0–100:
11
-
12
- | Score | Interpretação | Ação |
13
- |-------|--------------|------|
14
- | 90–100 | Definitivamente real — reproduzível mecanicamente | Reportar |
15
- | 75–89 | Provavelmente real — padrão forte de problema | Reportar com justificativa |
16
- | 50–74 | Incerto — depende de contexto não visível | Só reportar se CRITICAL/HIGH |
17
- | 25–49 | Provavelmente false positive | Ignorar |
18
- | 0–24 | Definitivamente false positive | Nunca reportar |
19
-
20
- **Threshold: reportar apenas findings com confidence ≥ 75.**
21
-
22
- O confidence score não aparece no output — aplique o filtro internamente. Output limpo = só findings que passaram ≥ 75.
23
-
24
- ---
25
-
26
- ## Categorias de False Positives (sempre ignorar)
27
-
28
- 1. **Violações pré-existentes** — código não alterado neste PR/branch. Se está no `git diff`, é relevante. Se não está, é dívida técnica para uma task de refactor separada.
29
-
30
- 2. **Linter/formatter-catchable** — naming trivial, whitespace, import order. Ferramentas automáticas cobrem isso; não gaste tempo de review manual neles.
31
-
32
- 3. **Preocupações arquiteturais especulativas** — "pode ser problema se escalar para 1M users", "esta abordagem pode causar N+1 se o dataset crescer". Só reporte se o problema for atual e concreto.
33
-
34
- 4. **Nitpicks abaixo de LOW** — preferências cosméticas sem impacto em corretude, performance ou manutenibilidade. Se não tem severidade, não reportar.
35
-
36
- 5. **Build errors** — se o código compila, não é build error. Não reporte problemas que o compilador já rejeitaria.
37
-
38
- ---
39
-
40
- ## Formato de Evidência Obrigatório
41
-
42
- Todo finding DEVE incluir:
43
-
44
- ```
45
- src/Application/Orders/OrderService.cs:42
46
- ```csharp
47
- catch { } // ← snippet do código ofensivo (≤ 5 linhas)
48
- ```
49
- Motivo: viola [EMPTY_CATCH] — exceções silenciadas impossibilitam diagnóstico.
50
- Fix: adicionar logging mínimo + re-throw, ou tratar o caso explicitamente.
51
- ```
52
-
53
- Campos obrigatórios por finding:
54
- - **File:line** — caminho relativo ao projeto + número da linha
55
- - **Snippet** — trecho do código ofensivo, ≤ 5 linhas
56
- - **Motivo** — por que viola o padrão (referência de regra ou checklist item)
57
- - **Fix** — sugestão concreta e acionável
58
-
59
- Findings sem file:line são invalidos e não devem ser reportados.
60
-
61
- ---
62
-
63
- ## Escopo: Apenas Código Alterado
64
-
65
- Focar exclusivamente em arquivos de:
66
-
67
- ```bash
68
- git diff --name-only main...HEAD
69
- ```
70
-
71
- Issues pré-existentes = dívida técnica para tasks de refactor dedicadas, **não** para revisões de feature PR.
72
-
73
- Se usando `scan-csharp.mjs` ou `scan-nextjs.mjs`, prefira `--diff` para limitar o escopo automaticamente.
74
-
75
- ---
76
-
77
- ## Saída Esperada
78
-
79
- Após filtrar por confidence ≥ 75 e ignorar false positives, a saída deve ser uma das duas formas:
80
-
81
- **Se há findings:**
82
- ```
83
- ## Code Review — [stack]
84
-
85
- ### CRITICAL
86
- - `src/Foo/Bar.cs:15` — [EMPTY_CATCH] Empty catch block swallows exceptions.
87
- ```csharp
88
- catch { }
89
- ```
90
- Fix: log + re-throw, ou tratar o caso.
91
-
92
- ### HIGH
93
- - `src/Foo/OrderService.cs:88` — [MISSING_CANCELLATION_TOKEN] Async method `ProcessOrderAsync` sem CancellationToken.
94
- Fix: adicionar `CancellationToken ct = default` como último parâmetro.
95
- ```
96
-
97
- **Se sem findings CRITICAL/HIGH:**
98
- ```
99
- ✅ Sem CRITICAL/HIGH em [stack] alterado. [N arquivos revisados]
100
- ```
@@ -1,151 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * scan-csharp.mjs
4
- *
5
- * Scans .cs files for MORPH-SPEC coding standard violations.
6
- * Executed locally by Claude via Bash — output returned to Claude.
7
- *
8
- * Usage:
9
- * node scan-csharp.mjs [path] # scan directory or file
10
- * node scan-csharp.mjs src/ # scan src/ recursively
11
- * node scan-csharp.mjs --summary # counts only, no details
12
- * node scan-csharp.mjs --diff # scan only changed files (git diff main...HEAD)
13
- * node scan-csharp.mjs --diff --base=develop # use different base branch
14
- *
15
- * Checks:
16
- * - UPPER_SNAKE_CASE constants → should be PascalCase
17
- * - Hungarian notation → strName, iCount, btnSubmit
18
- * - Missing CancellationToken → async methods without CT param
19
- * - String interpolation in logging → $"" in ILogger calls
20
- * - Empty catch blocks → catch { } or catch (E) { }
21
- */
22
-
23
- import { readdirSync, readFileSync, statSync, existsSync } from 'fs';
24
- import { join, extname, relative } from 'path';
25
- import { execSync } from 'child_process';
26
-
27
- const args = process.argv.slice(2);
28
- const diffMode = args.includes('--diff');
29
- const summaryOnly = args.includes('--summary');
30
- const baseBranch = args.find(a => a.startsWith('--base='))?.split('=')[1] ?? 'main';
31
- const targetPath = args.find(a => !a.startsWith('--')) ?? '.';
32
-
33
- const CHECKS = [
34
- {
35
- id: 'UPPER_SNAKE_CASE',
36
- severity: 'CRITICAL',
37
- pattern: /\bconst\s+\w+\s+([A-Z][A-Z_]{2,})\s*=/g,
38
- message: (m) => `Constant '${m[1]}' uses UPPER_SNAKE_CASE (anti-pattern in C#) → use PascalCase`,
39
- },
40
- {
41
- id: 'HUNGARIAN_NOTATION',
42
- severity: 'CRITICAL',
43
- pattern: /\b(str|int|bool|btn|lbl|txt|dbl|flt|obj|arr|lst)([A-Z]\w*)\b/g,
44
- message: (m) => `'${m[0]}' looks like Hungarian notation → rename to '${m[2].charAt(0).toLowerCase() + m[2].slice(1)}'`,
45
- },
46
- {
47
- id: 'MISSING_CANCELLATION_TOKEN',
48
- severity: 'HIGH',
49
- pattern: /public\s+async\s+Task(?:<[^>]+>)?\s+(\w+Async)\s*\(([^)]*)\)/g,
50
- message: (m) => {
51
- const params = m[2];
52
- if (params.includes('CancellationToken') || params.includes('ct ') || params.includes('ct,') || params.includes('ct)')) return null;
53
- return `Async method '${m[1]}' missing CancellationToken parameter`;
54
- },
55
- },
56
- {
57
- id: 'LOG_STRING_INTERPOLATION',
58
- severity: 'HIGH',
59
- pattern: /\.(LogInformation|LogWarning|LogError|LogDebug|LogCritical)\s*\(\s*\$"/g,
60
- message: () => 'String interpolation ($"") in log call → use message template with structured parameters',
61
- },
62
- {
63
- id: 'EMPTY_CATCH',
64
- severity: 'CRITICAL',
65
- pattern: /catch\s*(\([^)]*\))?\s*\{\s*\}/g,
66
- message: () => 'Empty catch block — exceptions are silently swallowed',
67
- },
68
- ];
69
-
70
- function collectCsFiles(dir) {
71
- if (!existsSync(dir)) return [];
72
- const stat = statSync(dir);
73
- if (stat.isFile()) return dir.endsWith('.cs') ? [dir] : [];
74
- const results = [];
75
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
76
- if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.git') {
77
- results.push(...collectCsFiles(join(dir, entry.name)));
78
- } else if (entry.isFile() && extname(entry.name) === '.cs') {
79
- results.push(join(dir, entry.name));
80
- }
81
- }
82
- return results;
83
- }
84
-
85
- function getChangedFiles(base) {
86
- try {
87
- const raw = execSync(`git diff --name-only ${base}...HEAD`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
88
- return raw.split('\n').map(f => f.trim()).filter(f => f.endsWith('.cs') && existsSync(f));
89
- } catch {
90
- return null;
91
- }
92
- }
93
-
94
- let mode = 'full';
95
- let files;
96
- if (diffMode) {
97
- const changed = getChangedFiles(baseBranch);
98
- if (changed !== null) {
99
- files = changed;
100
- mode = 'diff';
101
- } else {
102
- files = collectCsFiles(targetPath);
103
- }
104
- } else {
105
- files = collectCsFiles(targetPath);
106
- }
107
-
108
- const findings = [];
109
-
110
- for (const file of files) {
111
- const content = readFileSync(file, 'utf-8');
112
- const lines = content.split('\n');
113
-
114
- for (const check of CHECKS) {
115
- const regex = new RegExp(check.pattern.source, check.pattern.flags);
116
- let match;
117
- while ((match = regex.exec(content)) !== null) {
118
- const msg = check.message(match);
119
- if (!msg) continue;
120
- const lineNum = content.slice(0, match.index).split('\n').length;
121
- findings.push({
122
- severity: check.severity,
123
- id: check.id,
124
- file: relative(process.cwd(), file).replace(/\\/g, '/'),
125
- line: lineNum,
126
- message: msg,
127
- snippet: lines[lineNum - 1]?.trim().slice(0, 100),
128
- });
129
- }
130
- }
131
- }
132
-
133
- const bySeverity = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
134
- for (const f of findings) bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
135
-
136
- const summary = {
137
- scanned: files.length,
138
- findings: findings.length,
139
- bySeverity,
140
- clean: findings.length === 0,
141
- mode,
142
- ...(mode === 'diff' && { baseBranch, changedFilesCount: files.length }),
143
- };
144
-
145
- if (summaryOnly) {
146
- console.log(JSON.stringify(summary, null, 2));
147
- } else {
148
- console.log(JSON.stringify({ summary, findings }, null, 2));
149
- }
150
-
151
- process.exit(findings.some(f => f.severity === 'CRITICAL') ? 1 : 0);