@polymorphism-tech/morph-spec 8.46.0 → 9.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 (304) hide show
  1. package/CLAUDE.md +53 -44
  2. package/README.md +3 -4
  3. package/bin/morph-spec.js +38 -55
  4. package/bin/validate.js +5 -134
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +2 -2
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/CLAUDE.md +41 -101
  9. package/framework/MORPH.md +95 -252
  10. package/framework/agents.json +75 -18
  11. package/framework/commands/create-umbraco-lp.md +2 -0
  12. package/framework/commands/migrate-lp-to-umbraco.md +2 -0
  13. package/framework/commands/morph-apply.md +5 -28
  14. package/framework/commands/morph-archive.md +2 -2
  15. package/framework/commands/morph-hotfix.md +8 -8
  16. package/framework/commands/morph-infra.md +17 -203
  17. package/framework/commands/morph-media.md +3 -0
  18. package/framework/commands/morph-preflight.md +7 -31
  19. package/framework/commands/morph-proposal.md +2 -50
  20. package/framework/commands/morph-status.md +3 -3
  21. package/framework/commands/morph-troubleshoot.md +2 -14
  22. package/framework/docs/CLI.md +585 -286
  23. package/framework/evals/review-checklist.md +82 -41
  24. package/framework/hooks/README.md +10 -11
  25. package/framework/hooks/claude-code/core/comment-guard.js +1 -1
  26. package/framework/hooks/claude-code/core/denylist.json +33 -3
  27. package/framework/hooks/claude-code/core/enforce-phase-writes.js +16 -20
  28. package/framework/hooks/claude-code/core/gate-guard.js +2 -11
  29. package/framework/hooks/claude-code/core/pre-bash-denylist.js +38 -0
  30. package/framework/hooks/claude-code/core/protect-spec-files.js +30 -242
  31. package/framework/hooks/claude-code/core/state-sync.js +17 -19
  32. package/framework/hooks/claude-code/core/telemetry-log.js +3 -3
  33. package/framework/hooks/claude-code/core/validate-completion.js +33 -97
  34. package/framework/hooks/claude-code/core/warn-bash-source-write.js +31 -0
  35. package/framework/hooks/claude-code/core/worktree-context.js +5 -4
  36. package/framework/hooks/claude-code/statusline.py +55 -41
  37. package/framework/hooks/package.json +3 -0
  38. package/framework/hooks/shared/activity-logger.js +1 -1
  39. package/framework/hooks/shared/build-check.js +10 -6
  40. package/framework/hooks/shared/command-tokens.js +169 -0
  41. package/framework/hooks/shared/comment-rules.js +1 -1
  42. package/framework/hooks/shared/comment-scanner.js +10 -23
  43. package/framework/hooks/shared/comment-stripper.js +1 -1
  44. package/framework/hooks/shared/e2e-check.js +67 -31
  45. package/framework/hooks/shared/errata.js +72 -0
  46. package/framework/hooks/shared/feature-locator.js +1 -1
  47. package/framework/hooks/shared/frontend-locations.js +6 -0
  48. package/framework/hooks/shared/gate-question.js +18 -0
  49. package/framework/hooks/shared/phase-utils.js +15 -32
  50. package/framework/hooks/shared/slice-progress.js +118 -0
  51. package/framework/hooks/shared/spawn-command.js +23 -0
  52. package/framework/hooks/shared/state-reader.js +61 -87
  53. package/framework/hooks/shared/state-writer.js +3 -3
  54. package/framework/mcp/registry.json +3 -4
  55. package/framework/phases.json +23 -39
  56. package/framework/rules/ai-agents-standards.md +18 -16
  57. package/framework/rules/asaas-standards.md +3 -1
  58. package/framework/rules/csharp-standards.md +10 -8
  59. package/framework/rules/data-standards.md +5 -5
  60. package/framework/rules/dotnet-templates.md +1 -1
  61. package/framework/rules/frontend-standards.md +4 -2
  62. package/framework/rules/gsap-standards.md +10 -5
  63. package/framework/rules/hangfire-standards.md +3 -1
  64. package/framework/rules/infrastructure-standards.md +4 -2
  65. package/framework/rules/neon-auth-standards.md +3 -1
  66. package/framework/rules/neon-standards.md +6 -4
  67. package/framework/rules/nextjs-standards.md +13 -11
  68. package/framework/rules/nextjs-templates.md +1 -1
  69. package/framework/rules/resend-standards.md +3 -1
  70. package/framework/schemas/config.schema.json +14 -9
  71. package/framework/schemas/feature.schema.json +15 -52
  72. package/framework/skills/README.md +4 -5
  73. package/framework/skills/core/create-umbraco-lp/SKILL.md +3 -3
  74. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +3 -3
  75. package/framework/skills/core/morph-apply/SKILL.md +150 -223
  76. package/framework/skills/core/morph-hotfix/SKILL.md +34 -43
  77. package/framework/skills/core/morph-machine/SKILL.md +4 -4
  78. package/framework/skills/core/morph-media/SKILL.md +3 -3
  79. package/framework/skills/core/morph-plan/SKILL.md +138 -300
  80. package/framework/skills/core/morph-review/SKILL.md +112 -137
  81. package/framework/skills/core/morph-standards/SKILL.md +29 -41
  82. package/framework/skills/core/morph-uiux/SKILL.md +78 -153
  83. package/framework/standards/STANDARDS.json +90 -1219
  84. package/framework/standards/STANDARDS.meta.json +1305 -0
  85. package/framework/standards/ai-agents/evals-with-cache.md +2 -3
  86. package/framework/standards/ai-agents/llm-runtime-defaults.md +1 -1
  87. package/framework/standards/ai-agents/modalities-speech-to-text.md +36 -26
  88. package/framework/standards/ai-agents/prompt-sources.md +6 -4
  89. package/framework/standards/ai-agents/providers/model-registry.md +1 -1
  90. package/framework/standards/ai-agents/rag-custom-pgvector.md +67 -39
  91. package/framework/standards/ai-agents/setup.md +2 -2
  92. package/framework/standards/ai-agents/structured-output.md +1 -1
  93. package/framework/standards/ai-agents/sweet-spot.md +1 -1
  94. package/framework/standards/architecture/code-comments.md +8 -8
  95. package/framework/standards/architecture/vertical-slice/vertical-slice.md +18 -9
  96. package/framework/standards/backend/api/validation.md +135 -47
  97. package/framework/standards/backend/database/postgresql/database.md +11 -7
  98. package/framework/standards/backend/database/vector-search-rag.md +207 -324
  99. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +14 -8
  100. package/framework/standards/backend/dotnet/result-pattern.md +40 -6
  101. package/framework/standards/backend/dotnet/scalar-ui.md +13 -7
  102. package/framework/standards/backend/dotnet/scrutor.md +1 -1
  103. package/framework/standards/backend/dotnet/testing.md +1 -1
  104. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +7 -7
  105. package/framework/standards/backend/integrations/asaas/asaas-api.md +309 -165
  106. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +134 -154
  107. package/framework/standards/data/nosql/cache/redis.md +120 -44
  108. package/framework/standards/data/nosql/cosmos-db.md +114 -71
  109. package/framework/standards/frontend/design-system/animations.md +1 -1
  110. package/framework/standards/frontend/design-system/naming.md +1 -1
  111. package/framework/standards/frontend/nextjs/motion-patterns.md +45 -29
  112. package/framework/standards/frontend/nextjs/naming-conventions.md +1 -1
  113. package/framework/standards/infrastructure/docker/coolify-deploy.md +8 -6
  114. package/framework/standards/infrastructure/neon/neon-pgvector.md +120 -75
  115. package/framework/standards/infrastructure/neon/neon-setup.md +53 -31
  116. package/framework/standards/integration/mcp/mcp-tools.md +7 -7
  117. package/framework/templates/README.md +2 -3
  118. package/framework/templates/REGISTRY.json +6 -170
  119. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  120. package/framework/templates/code/dotnet/extensions/database-extensions.cs +1 -1
  121. package/framework/templates/code/dotnet/extensions/result-extensions.cs +27 -0
  122. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +2 -2
  123. package/framework/templates/docs/plan.md +72 -0
  124. package/framework/templates/dotnet/ai-kit/README.md +1 -9
  125. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +1 -1
  126. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
  127. package/framework/templates/infrastructure/docker/coolify.template.json +3 -3
  128. package/framework/templates/infrastructure/github/README.md +2 -1
  129. package/framework/templates/infrastructure/github/workflows/deploy-coolify.yml.hbs +2 -1
  130. package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
  131. package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
  132. package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
  133. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
  134. package/package.json +1 -1
  135. package/src/commands/e2e/e2e.js +2 -2
  136. package/src/commands/observability/cost.js +18 -60
  137. package/src/commands/observability/telemetry.js +3 -5
  138. package/src/commands/project/doctor-procs.js +1 -1
  139. package/src/commands/project/doctor.js +9 -9
  140. package/src/commands/project/fleet.js +4 -4
  141. package/src/commands/project/heavy.js +3 -3
  142. package/src/commands/project/init.js +6 -1
  143. package/src/commands/project/setup-infra-cmd.js +2 -1
  144. package/src/commands/project/stack-scan.js +58 -0
  145. package/src/commands/project/standards.js +79 -25
  146. package/src/commands/project/status.js +29 -69
  147. package/src/commands/project/update.js +33 -19
  148. package/src/commands/project/worktree.js +1 -1
  149. package/src/commands/state/advance.js +62 -46
  150. package/src/commands/state/approve.js +95 -138
  151. package/src/commands/state/archive.js +20 -84
  152. package/src/commands/state/auto-approval.js +68 -0
  153. package/src/commands/state/create.js +28 -1
  154. package/src/commands/state/delete.js +1 -1
  155. package/src/commands/state/finish.js +11 -23
  156. package/src/commands/state/gate-check.js +86 -95
  157. package/src/commands/state/gate-decision.js +6 -4
  158. package/src/commands/state/handoff.js +1 -1
  159. package/src/commands/state/list.js +9 -9
  160. package/src/commands/state/report-check.js +157 -311
  161. package/src/commands/state/retype.js +9 -3
  162. package/src/commands/validation/mutate.js +77 -14
  163. package/src/commands/validation/plan-check.js +81 -0
  164. package/src/commands/validation/validate-feature.js +60 -135
  165. package/src/commands/validation/verify.js +41 -82
  166. package/src/core/paths/output-schema.js +20 -67
  167. package/src/core/state/gate-order.js +5 -6
  168. package/src/core/state/lifecycle-audit.js +2 -2
  169. package/src/core/state/state-manager.js +17 -98
  170. package/src/core/templates/template-registry.js +2 -2
  171. package/src/core/templates/template-seed.js +22 -0
  172. package/src/core/work-types.js +10 -10
  173. package/src/dashboard/app/App.jsx +0 -2
  174. package/src/dashboard/app/components/ActivityFeed.jsx +2 -3
  175. package/src/dashboard/app/components/CommandPalette.jsx +7 -8
  176. package/src/dashboard/app/components/EntityLink.jsx +1 -2
  177. package/src/dashboard/app/components/Markdown.jsx +1 -1
  178. package/src/dashboard/app/components/Sidebar.jsx +1 -2
  179. package/src/dashboard/app/hooks/useMorphQuery.js +1 -1
  180. package/src/dashboard/app/lib/phases.js +2 -4
  181. package/src/dashboard/app/pages/Activity.jsx +1 -1
  182. package/src/dashboard/app/pages/FeatureDetail.jsx +139 -129
  183. package/src/dashboard/app/pages/Features.jsx +9 -9
  184. package/src/dashboard/app/pages/Guide.jsx +2 -2
  185. package/src/dashboard/app/pages/PhasePipeline.jsx +3 -4
  186. package/src/dashboard/app/pages/RulesMap.jsx +3 -3
  187. package/src/dashboard/app/pages/SkillsLibrary.jsx +3 -3
  188. package/src/dashboard/app/pages/Standards.jsx +1 -1
  189. package/src/dashboard/scanner/activity-scanner.js +6 -16
  190. package/src/dashboard/scanner/agents-scanner.js +1 -1
  191. package/src/dashboard/scanner/docs-scanner.js +5 -23
  192. package/src/dashboard/scanner/features-scanner.js +95 -60
  193. package/src/dashboard/scanner/index.js +0 -2
  194. package/src/dashboard/scanner/project-api.js +1 -1
  195. package/src/dashboard/scanner/rules-scanner.js +15 -10
  196. package/src/dashboard/scanner/skills-scanner.js +2 -3
  197. package/src/dashboard/scanner/standards-scanner.js +2 -1
  198. package/src/lib/ci/ci-verify.js +17 -1
  199. package/src/lib/ci/github-ci.js +1 -1
  200. package/src/lib/detectors/index.js +3 -8
  201. package/src/lib/generators/handoff-generator.js +34 -65
  202. package/src/lib/generators/settings-generator.js +11 -89
  203. package/src/lib/git/evidence-staleness.js +1 -1
  204. package/src/lib/git/tree-fingerprint.js +19 -7
  205. package/src/lib/git/tree-state.js +2 -2
  206. package/src/lib/heavy/cleanup.js +1 -5
  207. package/src/lib/installers/memory-installer.js +6 -8
  208. package/src/lib/mutation/commands.js +3 -2
  209. package/src/lib/{tasks/dotnet-test-introspection.js → mutation/dotnet-introspection.js} +17 -282
  210. package/src/lib/mutation/plan.js +14 -6
  211. package/src/lib/mutation/runner.js +1 -1
  212. package/src/lib/mutation/subset.js +46 -9
  213. package/src/lib/plan/artifact-vocabulary.js +60 -0
  214. package/src/lib/plan/checks.js +234 -0
  215. package/src/lib/plan/plan-parser.js +209 -0
  216. package/src/lib/plan/plan-template.js +18 -0
  217. package/src/lib/review-reports.js +222 -0
  218. package/src/lib/risk-detector.js +134 -135
  219. package/src/lib/specs/adr-index.js +50 -69
  220. package/src/lib/specs/design-seed.js +18 -0
  221. package/src/lib/specs/frontmatter.js +44 -0
  222. package/src/lib/specs/gfm-table.js +17 -0
  223. package/src/lib/specs/old-format.js +68 -0
  224. package/src/lib/specs/revocations.js +37 -95
  225. package/src/lib/specs/screen-checklist.js +18 -17
  226. package/src/lib/stack/dotnet-build-ignores.js +47 -0
  227. package/src/lib/stack/stack-profile.js +1 -1
  228. package/src/lib/stack/stack-scan.js +267 -0
  229. package/src/lib/standards/registry.js +43 -0
  230. package/src/lib/standards/sections.js +58 -0
  231. package/src/lib/tasks/eval-node.js +4 -12
  232. package/src/lib/tasks/test-nodes.js +1 -74
  233. package/src/lib/tasks/test-runner.js +75 -117
  234. package/src/lib/telemetry/metrics.js +8 -69
  235. package/src/lib/telemetry/telemetry-reader.js +5 -118
  236. package/src/lib/telemetry/verify-event.js +5 -7
  237. package/src/lib/validators/code-budget/code-budget-validator.js +1 -1
  238. package/src/lib/validators/contracts/contract-compliance-validator.js +2 -2
  239. package/src/lib/validators/reuse/reuse-validator.js +24 -48
  240. package/src/lib/validators/reuse/symbol-scanner.js +2 -4
  241. package/src/lib/validators/traceability-check.js +85 -129
  242. package/src/lib/validators/validation-runner.js +8 -88
  243. package/src/lib/validators/verify-runner.js +134 -301
  244. package/src/lib/worktree/docker-audit.js +1 -2
  245. package/src/lib/worktree/fleet-scanner.js +25 -38
  246. package/src/scripts/setup-infra.js +42 -22
  247. package/src/utils/agents-installer.js +92 -13
  248. package/src/utils/claude-settings-manager.js +0 -35
  249. package/src/utils/file-copier.js +34 -6
  250. package/src/utils/hooks-installer.js +16 -9
  251. package/src/utils/skills-installer.js +1 -2
  252. package/framework/commands/commit.md +0 -166
  253. package/framework/evals/trace-schema.md +0 -67
  254. package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
  255. package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
  256. package/framework/hooks/git/pre-commit/specs.sh +0 -50
  257. package/framework/hooks/shared/tasks-validator.js +0 -111
  258. package/framework/rubrics/backend.json +0 -41
  259. package/framework/rubrics/default.json +0 -36
  260. package/framework/rubrics/frontend.json +0 -36
  261. package/framework/rules/morph-task-tracking.md +0 -54
  262. package/framework/rules/morph-workflow.md +0 -244
  263. package/framework/schemas/tasks.schema.json +0 -79
  264. package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
  265. package/framework/skills/core/morph-implement/SKILL.md +0 -194
  266. package/framework/skills/core/morph-proposal/SKILL.md +0 -152
  267. package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
  268. package/framework/templates/docs/proposal.md +0 -192
  269. package/framework/templates/docs/spec.md +0 -57
  270. package/framework/templates/docs/ui-components.md +0 -52
  271. package/framework/templates/docs/ui-design-system.md +0 -76
  272. package/framework/templates/docs/ui-flows.md +0 -167
  273. package/framework/templates/examples/spec-examples.md +0 -91
  274. package/framework/templates/feature/decisions.md +0 -124
  275. package/framework/templates/feature/recap.md +0 -145
  276. package/framework/templates/project/validate.js +0 -97
  277. package/framework/templates/tasks.template.json +0 -17
  278. package/src/commands/state/usecase.js +0 -143
  279. package/src/commands/tasks/dag.js +0 -181
  280. package/src/dashboard/app/pages/Rubrics.jsx +0 -97
  281. package/src/dashboard/scanner/rubrics-scanner.js +0 -12
  282. package/src/lib/agents/output-collector.js +0 -76
  283. package/src/lib/evaluator-report.js +0 -91
  284. package/src/lib/specs/acervo-format.js +0 -70
  285. package/src/lib/specs/acervo-lifecycle.js +0 -264
  286. package/src/lib/specs/done-criteria-check.js +0 -200
  287. package/src/lib/specs/usecase-check.js +0 -301
  288. package/src/lib/specs/usecase-promoter.js +0 -301
  289. package/src/lib/specs/usecase-registry.js +0 -237
  290. package/src/lib/tasks/dispatch-planner.js +0 -319
  291. package/src/lib/tasks/mermaid-renderer.js +0 -132
  292. package/src/lib/tasks/task-classifier.js +0 -30
  293. package/src/lib/tasks/task-parser.js +0 -209
  294. package/src/lib/tasks/tasks-json-parser.js +0 -296
  295. package/src/lib/tasks/test-scope.js +0 -597
  296. package/src/lib/validators/architecture/architecture-validator.js +0 -270
  297. package/src/lib/validators/architecture/index.js +0 -7
  298. package/src/lib/validators/css/css-validator.js +0 -340
  299. package/src/lib/validators/css/index.js +0 -7
  300. package/src/lib/validators/design-system/design-system-validator.js +0 -237
  301. package/src/lib/validators/design-system/index.js +0 -7
  302. package/src/lib/validators/score-aggregator.js +0 -244
  303. package/src/lib/validators/ui/index.js +0 -7
  304. package/src/lib/validators/ui/ui-contrast-validator.js +0 -422
@@ -1,91 +0,0 @@
1
- # Spec Template Reference
2
-
3
- > **Layer:** 3 | **Load:** on-demand | **Keywords:** spec, specification, template
4
-
5
- **The canonical template is `docs/spec.md` of the template system** (REGISTRY id `spec`),
6
- resolved from the installed package — see `framework/templates/README.md`.
7
-
8
- This file contains extended examples for each spec section.
9
-
10
- ---
11
-
12
- ## Example: Entity (Pseudo-code)
13
-
14
- ```csharp
15
- class ProcessingJob {
16
- Guid Id
17
- string OriginalPhotoUrl // Azure Blob URL, max 500 chars
18
- string? ProcessedPhotoUrl // Nullable, populated after processing
19
- ProcessingStatus Status // Enum: Pending, Processing, Completed, Failed
20
- DateTime CreatedAt
21
- ICollection<ExecutionLog> Logs // 1:N relationship
22
- }
23
-
24
- enum ProcessingStatus {
25
- Pending = 0, Processing = 1, Completed = 2, // Normal flow
26
- Failed = 100 // Error states (high values)
27
- }
28
- ```
29
-
30
- ## Example: Command (Pseudo-code)
31
-
32
- ```csharp
33
- UploadPhotoCommand {
34
- Input: IFormFile photo, string? email
35
- Output: Guid jobId
36
-
37
- Handler:
38
- 1. Validate file (size <= 10MB, type in [.jpg, .png])
39
- 2. Upload to Azure Blob Storage
40
- 3. Create ProcessingJob entity (status = Pending)
41
- 4. Enqueue Hangfire background job
42
- 5. Return jobId
43
- }
44
- ```
45
-
46
- ## Example: API Endpoints
47
-
48
- ```csharp
49
- PhotoProcessingController {
50
- POST /api/upload → multipart/form-data → { jobId: Guid }
51
- GET /api/status/{id} → jobId → { status, progress, createdAt }
52
- GET /api/download/{id} → jobId → Redirect to Blob URL or 404
53
- }
54
- ```
55
-
56
- ## Example: Flow
57
-
58
- ```
59
- Upload Flow (Actor: User)
60
- 1. User selects photo → System validates (size, type) → If invalid: show error
61
- 2. User sees preview → clicks "Upload"
62
- 3. System creates ProcessingJob → uploads to Blob → enqueues Hangfire job → returns jobId
63
- 4. System navigates to /processing/{jobId} → polls every 5s
64
- End State: User on progress page, job processing in background
65
- ```
66
-
67
- ## Example: ADR
68
-
69
- ### ADR-001: Use Hangfire for Background Jobs
70
- **Status:** Accepted
71
- **Context:** Need background processing for AI photo transformation (30-120s).
72
- **Decision:** Hangfire (self-hosted).
73
- **Alternatives:**
74
- 1. Azure Functions — serverless, auto-scaling, but cold start + $10/mo for 50k jobs
75
- 2. Hangfire — zero cost, simpler, but scales with app
76
- 3. Quartz.NET — more features, but steeper learning curve
77
- **Trade-offs:** Simplicity vs Features (Hangfire sufficient for MVP)
78
-
79
- ## Example: Cost Estimate
80
-
81
- | Resource | SKU | Monthly | Justification |
82
- |----------|-----|---------|---------------|
83
- | Blob Storage | LRS | $0.02 | Store photos, low redundancy OK |
84
- | Azure SQL | Basic | $4.99 | < 100k jobs/month |
85
- | Container App | Consumption | $0.49 | Scale to zero |
86
- | Hangfire | Self-hosted | $0.00 | In-process |
87
- | **Total** | | **~$5.50** | |
88
-
89
- ---
90
-
91
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,124 +0,0 @@
1
- # Architecture Decision Records - {{titleCase FEATURE_NAME}}
2
-
3
- ## ADR-001: {Decision Title}
4
-
5
- **Date:** {{DATE}}
6
- **Status:** Proposed | Accepted | Deprecated | Superseded
7
- **Deciders:** MORPH Agents, Developer
8
- **Alcance:** feature
9
-
10
- ### Context
11
-
12
- {Describe the context and problem that led to this decision}
13
-
14
- ### Decision
15
-
16
- {Describe the decision made}
17
-
18
- ### Consequences
19
-
20
- **Pros:**
21
- - {Positive consequence 1}
22
- - {Positive consequence 2}
23
-
24
- **Cons:**
25
- - {Negative consequence 1}
26
-
27
- **Risks:**
28
- - {Identified risk}
29
-
30
- ### Alternatives Considered
31
-
32
- #### Option A: {Name}
33
- - Pros: {advantages}
34
- - Cons: {disadvantages}
35
- - **Rejected because:** {reason}
36
-
37
- #### Option B: {Name}
38
- - Pros: {advantages}
39
- - Cons: {disadvantages}
40
- - **Rejected because:** {reason}
41
-
42
- ---
43
-
44
- {{#if (eq STACK "nextjs-neon")}}
45
- ## ADR-002: Database Access Strategy
46
-
47
- **Date:** {{DATE}}
48
- **Status:** Accepted
49
-
50
- ### Context
51
-
52
- Need to decide how the .NET API accesses Neon PostgreSQL.
53
-
54
- ### Decision
55
-
56
- Use Dapper with Npgsql for direct SQL queries. No EF Core.
57
-
58
- ### Consequences
59
-
60
- **Pros:**
61
- - Full control over SQL queries
62
- - Better performance (no ORM overhead)
63
- - Direct access to PostgreSQL features (jsonb, pgvector, functions)
64
- - RLS policies apply naturally through connection
65
-
66
- **Cons:**
67
- - No automatic migrations (use Neon CLI / dotnet ef instead)
68
- - Manual SQL query writing
69
- - No change tracking
70
-
71
- ---
72
-
73
- ## ADR-003: Auth Strategy
74
-
75
- **Date:** {{DATE}}
76
- **Status:** Accepted
77
-
78
- ### Context
79
-
80
- Need authentication for both Next.js frontend and .NET API.
81
-
82
- ### Decision
83
-
84
- Use Neon Auth (Better Auth) for authentication. Auth data lives in the Neon database. JWT validated by .NET API middleware.
85
-
86
- ### Consequences
87
-
88
- **Pros:**
89
- - Auth data in same database — no external provider, no sync delays
90
- - RLS policies work with Neon Auth JWT via auth.user_id() / pg_session_jwt
91
- - Built-in social login, email/password via @neondatabase/auth SDK
92
- - Branch isolation — each Neon branch gets isolated auth data
93
- - No webhooks needed — query neon_auth schema directly
94
-
95
- **Cons:**
96
- - Neon Auth is currently in Beta
97
- - JWT must be forwarded to .NET API for backend auth
98
- {{/if}}
99
-
100
- ---
101
-
102
- ## Template for New ADRs
103
-
104
- ```markdown
105
- ## ADR-XXX: {Title}
106
-
107
- **Date:**
108
- **Status:** Proposed | Accepted | Deprecated | Superseded
109
- **Alcance:** feature | projeto — `projeto` when the rule holds beyond this feature: `morph-spec finish` copies it to `.morph/specs/adrs/`, the folder brainstorming and plan read instead of archived decisions.md
110
-
111
- ### Context
112
- {Why is this decision needed?}
113
-
114
- ### Decision
115
- {What was decided?}
116
-
117
- ### Consequences
118
- **Pros:** {list}
119
- **Cons:** {list}
120
- ```
121
-
122
- ---
123
-
124
- *Generated by MORPH Framework*
@@ -1,145 +0,0 @@
1
- # Feature Recap: {{titleCase FEATURE_NAME}}
2
-
3
- ## Summary
4
-
5
- | Field | Value |
6
- |-------|-------|
7
- | **Feature ID** | {{FEATURE_NAME}} |
8
- | **Completed** | {{DATE}} |
9
- | **Total Tasks** | {X} |
10
- | **Time Spent** | {X}h |
11
- | **Agents Used** | {list} |
12
- {{#if STACK}}| **Stack** | {{STACK}} |{{/if}}
13
-
14
- ---
15
-
16
- ## Tasks Completed
17
-
18
- | ID | Title | Category | Duration |
19
- |----|-------|----------|----------|
20
- | T001 | {title} | {{#if (eq STACK "nextjs-neon")}}Database{{else}}{category}{{/if}} | {X}min |
21
- | T002 | {title} | {{#if (eq STACK "nextjs-neon")}}Backend{{else}}{category}{{/if}} | {X}min |
22
- | T003 | {title} | {{#if (eq STACK "nextjs-neon")}}Frontend{{else}}{category}{{/if}} | {X}min |
23
-
24
- ---
25
-
26
- {{#if (eq STACK "nextjs-neon")}}
27
- ## Validation Results
28
-
29
- | Validator | Status | Details |
30
- |-----------|--------|---------|
31
- | contract-compliance | Pass/Fail | {details} |
32
- | architecture | Pass/Fail | {details} |
33
- | design-system | Pass/Fail | {details} |
34
- | coding-standards | Pass/Fail | {details} |
35
-
36
- ---
37
-
38
- {{/if}}
39
- ## What Was Delivered
40
-
41
- ### Functionality
42
- - {Functionality 1 delivered}
43
- - {Functionality 2 delivered}
44
- - {Functionality 3 delivered}
45
-
46
- {{#if (eq STACK "nextjs-neon")}}
47
- ### Database (Neon PostgreSQL)
48
- - Tables: {list}
49
- - RLS Policies: {count} policies
50
- - Migrations: {count} files
51
-
52
- ### Backend API (.NET)
53
- - Endpoints: {count} endpoints
54
- - Services: {list}
55
-
56
- ### Frontend (Next.js)
57
- - Pages: {list}
58
- - Components: {list}
59
- {{/if}}
60
-
61
- ---
62
-
63
- ## Files Created
64
-
65
- ```
66
- {{#if (eq STACK "nextjs-neon")}}
67
- migrations/{files}
68
- backend/src/{files}
69
- frontend/src/{files}
70
- {{else}}
71
- {list of created files}
72
- {{/if}}
73
- ```
74
-
75
- ## Files Modified
76
-
77
- ```
78
- {list of modified files}
79
- ```
80
-
81
- ---
82
-
83
- ## Architecture Decisions
84
-
85
- | Decision | Rationale |
86
- |----------|-----------|
87
- | {Decision 1} | {Reason} |
88
- | {Decision 2} | {Reason} |
89
-
90
- See full ADRs in `decisions.md`
91
-
92
- ---
93
-
94
- ## Test Coverage
95
-
96
- | Type | Files | Coverage |
97
- |------|-------|----------|
98
- | {{#if (eq STACK "nextjs-neon")}}Backend Unit{{else}}Unit Tests{{/if}} | {X} | {X}% |
99
- | {{#if (eq STACK "nextjs-neon")}}Frontend Component{{else}}Integration Tests{{/if}} | {X} | {X}% |
100
-
101
- ---
102
-
103
- ## Lessons Learned
104
-
105
- ### What Went Well
106
- - {Positive point 1}
107
- - {Positive point 2}
108
-
109
- ### What Could Be Improved
110
- - {Improvement point 1}
111
- - {Improvement point 2}
112
-
113
- ### Recommendations for Future
114
- - {Recommendation 1}
115
- - {Recommendation 2}
116
-
117
- ---
118
-
119
- ## Metrics
120
-
121
- | Metric | Value |
122
- |--------|-------|
123
- | Tasks Completed | {X}/{X} |
124
- | Checkpoints Passed | {X} |
125
- {{#if (eq STACK "nextjs-neon")}}| Validation Passes | {X}/{X} |
126
- {{else}}| Code Reviews | {X} |
127
- {{/if}}| Bugs Found | {X} |
128
- | Bugs Fixed | {X} |
129
-
130
- ---
131
-
132
- ## Related Resources
133
-
134
- - **Proposal:** `proposal.md`
135
- - **Spec:** `spec.md`
136
- {{#if (eq STACK "nextjs-neon")}}- **Contracts (.NET):** `contracts.cs`
137
- - **Contracts (TS):** `contracts.ts`
138
- {{else}}- **Contracts:** `contracts.cs`
139
- {{/if}}- **Tasks:** `tasks.json`
140
- - **Decisions:** `decisions.md`
141
- - **PR:** {link}
142
-
143
- ---
144
-
145
- *Generated by MORPH Framework on {{DATE}}*
@@ -1,97 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const validator = process.argv[2];
4
- const isJson = process.argv.includes('--json');
5
-
6
- if (!validator) {
7
- console.error('Usage: node bin/validate.js <validator> [--json]');
8
- process.exit(1);
9
- }
10
-
11
- const { execSync } = await import('child_process');
12
- const { existsSync } = await import('fs');
13
- const { join } = await import('path');
14
-
15
- const cwd = process.cwd();
16
-
17
- const results = {
18
- validator,
19
- errors: 0,
20
- warnings: 0,
21
- passed: true,
22
- issues: [],
23
- };
24
-
25
- function runCommand(cmd, options = {}) {
26
- try {
27
- const stdout = execSync(cmd, { cwd, stdio: ['pipe', 'pipe', 'pipe'], ...options }).toString();
28
- return { success: true, stdout, stderr: '' };
29
- } catch (err) {
30
- return {
31
- success: false,
32
- stdout: err.stdout?.toString() || '',
33
- stderr: err.stderr?.toString() || err.message,
34
- };
35
- }
36
- }
37
-
38
- const hasFrontend = existsSync(join(cwd, 'src/frontend')) || existsSync(join(cwd, 'frontend'));
39
- const hasBackend = existsSync(join(cwd, 'src/backend')) || existsSync(join(cwd, 'backend'));
40
- const hasSln = existsSync(join(cwd, 'src/backend/backend.sln')) ||
41
- existsSync(join(cwd, 'src/backend/Backend.sln'));
42
-
43
- const frontendDir = existsSync(join(cwd, 'src/frontend')) ? 'src/frontend' : 'frontend';
44
- const backendDir = existsSync(join(cwd, 'src/backend')) ? 'src/backend' : 'backend';
45
-
46
- switch (validator) {
47
- case 'architecture': {
48
- if (hasBackend && hasSln) {
49
- const slnFile = hasSln ? (
50
- existsSync(join(cwd, 'src/backend/backend.sln')) ? 'backend.sln' : 'Backend.sln'
51
- ) : '.';
52
- const result = runCommand(`dotnet build ${slnFile} --no-restore -warnaserror`, { cwd: join(cwd, backendDir) });
53
- if (!result.success) {
54
- results.errors++;
55
- results.passed = false;
56
- results.issues.push({ level: 'error', message: `dotnet build failed: ${result.stderr.split('\n')[0]}` });
57
- }
58
- }
59
- break;
60
- }
61
-
62
- case 'nextjs-component':
63
- case 'packages':
64
- case 'design-system': {
65
- if (hasFrontend) {
66
- const result = runCommand('npx tsc --noEmit', { cwd: join(cwd, frontendDir) });
67
- if (!result.success) {
68
- results.errors++;
69
- results.passed = false;
70
- results.issues.push({ level: 'error', message: `TypeScript errors found. Run: npx tsc --noEmit` });
71
- }
72
- }
73
- break;
74
- }
75
-
76
- case 'ui-contrast':
77
- case 'css': {
78
- results.issues.push({ level: 'info', message: `${validator} requires manual review` });
79
- break;
80
- }
81
-
82
- default:
83
- results.issues.push({ level: 'warning', message: `Unknown validator: ${validator}` });
84
- break;
85
- }
86
-
87
- if (isJson) {
88
- console.log(JSON.stringify(results, null, 2));
89
- } else {
90
- const icon = results.passed ? '✅' : '❌';
91
- console.log(`${icon} Validator: ${validator} — ${results.passed ? 'PASSED' : `FAILED (${results.errors} errors)`}`);
92
- for (const issue of results.issues) {
93
- console.log(` [${issue.level}] ${issue.message}`);
94
- }
95
- }
96
-
97
- process.exit(results.passed ? 0 : 1);
@@ -1,17 +0,0 @@
1
- {
2
- "version": "1.0",
3
- "feature": "{{featureName}}",
4
- "tasks": [
5
- {
6
- "id": "T1",
7
- "title": "Example task title",
8
- "description": "What this task accomplishes and why",
9
- "dependencies": [],
10
- "effort": "M",
11
- "doneCriteria": "Verifiable acceptance condition stated in one sentence",
12
- "status": "pending",
13
- "outputs": [],
14
- "group": "backend"
15
- }
16
- ]
17
- }
@@ -1,143 +0,0 @@
1
- /**
2
- * `morph-spec usecase reserve [--count <n>] [--feature <name>] [--json]` —
3
- * atomically mint the next N `UC-{nn}` numbers, shared across every worktree
4
- * of this repo. See `usecase-registry.js` for why this exists (worktrees only
5
- * ever see their own tree, so an independent max+1 scan collides).
6
- *
7
- * `--feature` is more than an audit label: `usecase-promoter.js`'s collision
8
- * guard uses the reservation record to tell a legitimate cross-feature
9
- * correction (never reserved — reusing a published number by design) from an
10
- * accidental collision (both features reserved the same id). Passing it is
11
- * how `morph-plan` gets that protection; omitting it degrades to "reserved,
12
- * no owner recorded" — still collision-free, just unable to name the
13
- * conflicting feature if one ever surfaces.
14
- *
15
- * `morph-spec usecase check <feature>` — see `usecaseCheckCommand` below.
16
- */
17
-
18
- import chalk from 'chalk';
19
- import { existsSync, readdirSync } from 'fs';
20
- import { join } from 'path';
21
- import { resolveGitCommonDir } from '../../../framework/hooks/shared/git-paths.js';
22
- import { reserveUseCases } from '../../lib/specs/usecase-registry.js';
23
- import { checkUseCases } from '../../lib/specs/usecase-check.js';
24
- import { checkLifecycle } from '../../lib/specs/acervo-lifecycle.js';
25
- import { parseTasksJsonLenient } from '../../lib/tasks/tasks-json-parser.js';
26
- import { isValidFeatureName } from '../project/worktree.js';
27
- import { printLifecycleWarnings } from '../tasks/dag.js';
28
-
29
- /**
30
- * Best-effort feature-name inference when `--feature` is omitted: only when
31
- * exactly one active feature exists is the guess unambiguous. Anything else
32
- * (zero, or more than one) is left null rather than guessed wrong — a wrong
33
- * guess would poison the collision guard's provenance record.
34
- */
35
- function inferActiveFeature(cwd) {
36
- const featuresDir = join(cwd, '.morph', 'features');
37
- try {
38
- if (!existsSync(featuresDir)) return null;
39
- const entries = readdirSync(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory());
40
- return entries.length === 1 ? entries[0].name : null;
41
- } catch {
42
- return null;
43
- }
44
- }
45
-
46
- /**
47
- * @param {{ count?: string, feature?: string, json?: boolean, cwd?: string }} [options]
48
- */
49
- export function usecaseReserveCommand(options = {}) {
50
- const cwd = options.cwd || process.cwd();
51
- const count = Number.parseInt(options.count, 10);
52
- const n = Number.isInteger(count) && count > 0 ? count : 1;
53
- const feature = options.feature || inferActiveFeature(cwd) || null;
54
-
55
- let gitCommonDir = null;
56
- try { gitCommonDir = resolveGitCommonDir(cwd); } catch { gitCommonDir = null; }
57
-
58
- let result;
59
- try {
60
- result = reserveUseCases(cwd, { feature, count: n, gitCommonDir });
61
- } catch (error) {
62
- if (options.json) {
63
- console.log(JSON.stringify({ reserved: false, error: error.message }));
64
- process.exit(1);
65
- }
66
- console.error(chalk.red(`\n❌ ${error.message}\n`));
67
- process.exit(1);
68
- }
69
-
70
- const warning = gitCommonDir
71
- ? null
72
- : 'projeto fora de um repositório git — numeração protegida só localmente; paralelismo entre worktrees NÃO está garantido.';
73
-
74
- if (options.json) {
75
- console.log(JSON.stringify({ reserved: true, ...result, feature, warning }));
76
- process.exit(0);
77
- }
78
-
79
- console.log(chalk.green(`\n✅ Reservado: ${result.numbers.join(' ')}`));
80
- if (feature) console.log(chalk.gray(` feature: ${feature}`));
81
- if (warning) console.log(chalk.yellow(`⚠️ ${warning}\n`));
82
- else console.log('');
83
- process.exit(0);
84
- }
85
-
86
- /**
87
- * `morph-spec usecase check <feature> [--json]` — the use-case half of `dag`,
88
- * runnable before `tasks.json` exists: the feature's use cases and the
89
- * revocations its `spec.md` declares, against the acervo's lifecycle. With a
90
- * `tasks.json`, also the task → use case plumbing `dag` checks.
91
- *
92
- * Exit 1 only for what `dag` also refuses (a task pointing at a use case that
93
- * does not exist, a tasks.json that does not validate); lifecycle findings are
94
- * warnings.
95
- *
96
- * @param {string} feature
97
- * @param {{ json?: boolean, cwd?: string }} [options]
98
- */
99
- export async function usecaseCheckCommand(feature, options = {}) {
100
- const cwd = options.cwd || process.cwd();
101
- const fail = (error) => {
102
- if (options.json) console.log(JSON.stringify({ feature, error }));
103
- else console.error(chalk.red(`\n❌ ${error}\n`));
104
- process.exit(1);
105
- };
106
-
107
- if (!isValidFeatureName(feature)) fail(`nome de feature inválido: "${feature}"`);
108
- const featureDir = join(cwd, '.morph', 'features', feature);
109
- if (!existsSync(featureDir)) fail(`feature não encontrada: .morph/features/${feature}`);
110
-
111
- const tasksPath = join(featureDir, '2-plan', 'tasks.json');
112
- let tasksData = null;
113
- if (existsSync(tasksPath)) {
114
- try {
115
- ({ data: tasksData } = await parseTasksJsonLenient(tasksPath));
116
- } catch (error) {
117
- fail(`tasks.json inválido: ${error.message}`);
118
- }
119
- }
120
-
121
- const useCases = tasksData ? checkUseCases(tasksData, join(featureDir, '2-plan', 'usecases')) : null;
122
- const lifecycle = checkLifecycle({ cwd, featureDir, tasksData });
123
- const broken = useCases?.errors.length > 0;
124
-
125
- if (options.json) {
126
- console.log(JSON.stringify({ feature, useCases, lifecycle }, null, 2));
127
- process.exit(broken ? 1 : 0);
128
- }
129
-
130
- if (broken) {
131
- console.error(chalk.red(`\n❌ Use cases — ${useCases.errors.length} erro(s)\n`));
132
- for (const e of useCases.errors) console.error(chalk.red(` ${e}`));
133
- }
134
- if (useCases?.warnings.length) {
135
- console.error(chalk.yellow(`\n⚠ Use cases — ${useCases.warnings.length} aviso(s)`));
136
- for (const w of useCases.warnings) console.error(chalk.yellow(` ${w}`));
137
- }
138
- printLifecycleWarnings(lifecycle);
139
- if (!broken && !useCases?.warnings.length && !lifecycle.warnings.length) {
140
- console.log(chalk.green(`\n✅ ${feature}: use cases e acervo sem achados\n`));
141
- }
142
- process.exit(broken ? 1 : 0);
143
- }