@polymorphism-tech/morph-spec 3.1.0 → 4.2.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 (333) hide show
  1. package/CLAUDE.md +882 -3
  2. package/README.md +79 -18
  3. package/bin/detect-agents.js +1 -1
  4. package/bin/morph-spec.js +163 -26
  5. package/bin/task-manager.cjs +101 -7
  6. package/bin/validate.js +1 -1
  7. package/docs/cli-auto-detection.md +219 -0
  8. package/docs/getting-started.md +0 -5
  9. package/docs/llm-interaction-config.md +735 -0
  10. package/docs/troubleshooting.md +269 -0
  11. package/docs/v3.0/AGENTS.md +521 -0
  12. package/docs/v3.0/ANALYSIS.md +555 -0
  13. package/docs/v3.0/ARCHITECTURE.md +436 -0
  14. package/docs/v3.0/EXECUTION-FLOW.md +1304 -0
  15. package/docs/v3.0/FEATURES.md +688 -0
  16. package/docs/v3.0/README.md +231 -0
  17. package/docs/v3.0/ROADMAP.md +801 -0
  18. package/docs/validation-checklist.md +0 -1
  19. package/package.json +5 -1
  20. package/src/commands/agents/index.js +4 -0
  21. package/src/commands/agents/spawn-team.js +172 -0
  22. package/src/commands/{create-story.js → feature/create-story.js} +357 -354
  23. package/src/commands/feature/index.js +6 -0
  24. package/src/commands/{shard-spec.js → feature/shard-spec.js} +2 -2
  25. package/src/commands/{sprint-status.js → feature/sprint-status.js} +1 -1
  26. package/src/commands/{generate-context.js → generation/generate-context.js} +40 -40
  27. package/src/commands/{generate.js → generation/generate.js} +130 -3
  28. package/src/commands/generation/index.js +5 -0
  29. package/src/commands/index.js +16 -0
  30. package/src/commands/learning/capture-pattern.js +121 -0
  31. package/src/commands/learning/index.js +5 -0
  32. package/src/commands/learning/search-patterns.js +126 -0
  33. package/src/commands/{detect-agents.js → project/detect-agents.js} +178 -178
  34. package/src/commands/project/detect-workflow.js +174 -0
  35. package/src/commands/{detect.js → project/detect.js} +104 -104
  36. package/src/commands/{doctor.js → project/doctor.js} +356 -356
  37. package/src/commands/project/index.js +10 -0
  38. package/src/commands/{init.js → project/init.js} +305 -258
  39. package/src/commands/{sync.js → project/sync.js} +167 -167
  40. package/src/commands/{update.js → project/update.js} +240 -204
  41. package/src/commands/{advance-phase.js → state/advance-phase.js} +416 -266
  42. package/src/commands/state/approve.js +221 -0
  43. package/src/commands/state/index.js +8 -0
  44. package/src/commands/{rollback-phase.js → state/rollback-phase.js} +185 -185
  45. package/src/commands/{state.js → state/state.js} +334 -334
  46. package/src/commands/{validate-phase.js → state/validate-phase.js} +221 -221
  47. package/src/commands/tasks/index.js +4 -0
  48. package/src/commands/{task.js → tasks/task.js} +78 -78
  49. package/src/commands/templates/index.js +8 -0
  50. package/src/commands/templates/template-customize.js +101 -0
  51. package/src/commands/templates/template-list.js +128 -0
  52. package/src/commands/templates/template-render.js +95 -0
  53. package/src/commands/templates/template-show.js +131 -0
  54. package/src/commands/templates/template-validate.js +91 -0
  55. package/src/commands/utils/index.js +7 -0
  56. package/src/commands/utils/migrate-state.js +158 -0
  57. package/src/commands/{session-summary.js → utils/session-summary.js} +291 -291
  58. package/src/commands/{troubleshoot.js → utils/troubleshoot.js} +222 -222
  59. package/src/commands/utils/upgrade.js +346 -0
  60. package/src/commands/{analyze-blazor-concurrency.js → validation/analyze-blazor-concurrency.js} +193 -193
  61. package/src/commands/validation/index.js +8 -0
  62. package/src/commands/{lint-fluent.js → validation/lint-fluent.js} +352 -352
  63. package/src/commands/{validate-blazor-state.js → validation/validate-blazor-state.js} +210 -210
  64. package/src/commands/{validate-blazor.js → validation/validate-blazor.js} +156 -156
  65. package/src/commands/{validate-css.js → validation/validate-css.js} +84 -84
  66. package/src/core/index.js +10 -0
  67. package/src/core/registry/command-registry.js +302 -0
  68. package/src/core/registry/index.js +8 -0
  69. package/src/core/registry/validator-registry.js +204 -0
  70. package/src/core/state/index.js +8 -0
  71. package/src/core/state/phase-state-machine.js +214 -0
  72. package/src/{lib → core/state}/state-manager.js +572 -414
  73. package/src/core/templates/index.js +9 -0
  74. package/src/core/templates/template-data-sources.js +325 -0
  75. package/src/core/templates/template-registry.js +335 -0
  76. package/src/core/templates/template-renderer.js +477 -0
  77. package/src/core/templates/template-validator.js +296 -0
  78. package/src/core/workflows/index.js +7 -0
  79. package/src/core/workflows/workflow-detector.js +354 -0
  80. package/src/generator/config-generator.js +206 -0
  81. package/src/generator/templates/config.json.template +40 -0
  82. package/src/generator/templates/project.md.template +67 -0
  83. package/src/lib/{complexity-analyzer.js → analysis/complexity-analyzer.js} +441 -441
  84. package/src/lib/analysis/index.js +7 -0
  85. package/src/lib/checkpoints/checkpoint-hooks.js +258 -0
  86. package/src/lib/checkpoints/index.js +7 -0
  87. package/src/lib/detectors/config-detector.js +223 -223
  88. package/src/lib/detectors/conversation-analyzer.js +163 -163
  89. package/src/lib/{design-system-detector.js → detectors/design-system-detector.js} +187 -187
  90. package/src/lib/detectors/index.js +87 -84
  91. package/src/lib/detectors/standards-generator.js +275 -275
  92. package/src/lib/detectors/structure-detector.js +245 -245
  93. package/src/lib/{context-generator.js → generators/context-generator.js} +526 -516
  94. package/src/lib/generators/index.js +10 -0
  95. package/src/lib/generators/metadata-extractor.js +387 -0
  96. package/src/lib/{recap-generator.js → generators/recap-generator.js} +205 -205
  97. package/src/lib/learning/index.js +7 -0
  98. package/src/lib/orchestration/index.js +7 -0
  99. package/src/lib/{team-orchestrator.js → orchestration/team-orchestrator.js} +323 -323
  100. package/src/lib/stacks/index.js +7 -0
  101. package/src/lib/{stack-resolver.js → stacks/stack-resolver.js} +180 -148
  102. package/src/lib/standards/index.js +7 -0
  103. package/src/lib/{standards-context-injector.js → standards/standards-context-injector.js} +298 -288
  104. package/src/lib/troubleshooting/index.js +8 -0
  105. package/src/lib/{troubleshoot-grep.js → troubleshooting/troubleshoot-grep.js} +204 -204
  106. package/src/lib/{troubleshoot-index.js → troubleshooting/troubleshoot-index.js} +144 -144
  107. package/src/lib/validators/architecture/architecture-validator.js +387 -0
  108. package/src/lib/validators/architecture/index.js +7 -0
  109. package/src/lib/validators/architecture-validator.js +40 -367
  110. package/src/lib/{blazor-concurrency-analyzer.js → validators/blazor/blazor-concurrency-analyzer.js} +277 -288
  111. package/src/lib/{blazor-state-validator.js → validators/blazor/blazor-state-validator.js} +279 -291
  112. package/src/lib/{blazor-validator.js → validators/blazor/blazor-validator.js} +369 -374
  113. package/src/lib/validators/blazor/index.js +9 -0
  114. package/src/lib/validators/content/content-validator.js +351 -0
  115. package/src/lib/validators/content/index.js +7 -0
  116. package/src/lib/validators/content-validator.js +164 -0
  117. package/src/lib/validators/{contract-compliance-validator.js → contracts/contract-compliance-validator.js} +273 -273
  118. package/src/lib/validators/contracts/index.js +7 -0
  119. package/src/lib/{css-validator.js → validators/css/css-validator.js} +352 -352
  120. package/src/lib/validators/css/index.js +7 -0
  121. package/src/lib/validators/{design-system-validator.js → design-system/design-system-validator.js} +231 -231
  122. package/src/lib/validators/design-system/index.js +7 -0
  123. package/src/lib/validators/package-validator.js +41 -340
  124. package/src/lib/validators/packages/index.js +7 -0
  125. package/src/lib/validators/packages/package-validator.js +360 -0
  126. package/src/lib/validators/shared/index.js +12 -0
  127. package/src/lib/validators/shared/issue-counter.js +18 -0
  128. package/src/lib/validators/shared/result-formatter.js +124 -0
  129. package/src/lib/{spec-validator.js → validators/spec-validator.js} +258 -258
  130. package/src/lib/validators/ui/index.js +7 -0
  131. package/src/lib/validators/ui/ui-contrast-validator.js +422 -0
  132. package/src/lib/validators/ui-contrast-validator.js +31 -409
  133. package/src/lib/{validation-runner.js → validators/validation-runner.js} +286 -284
  134. package/src/llm/analyzer.js +215 -0
  135. package/src/llm/environment-detector.js +43 -0
  136. package/src/llm/few-shot-examples.js +216 -0
  137. package/src/llm/project-config-schema.json +188 -0
  138. package/src/llm/prompt-builder.js +96 -0
  139. package/src/orchestrator.js +206 -0
  140. package/src/sanitizer/context-sanitizer.js +221 -0
  141. package/src/sanitizer/patterns.js +163 -0
  142. package/src/scanner/project-scanner.js +242 -0
  143. package/src/ui/diff-display.js +91 -0
  144. package/src/ui/interactive-wizard.js +96 -0
  145. package/src/ui/user-review.js +211 -0
  146. package/src/ui/wizard-questions.js +188 -0
  147. package/src/utils/color-utils.js +70 -0
  148. package/src/utils/file-copier.js +188 -189
  149. package/src/utils/process-handler.js +97 -0
  150. package/src/writer/file-writer.js +86 -0
  151. package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +3 -3
  152. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +59 -0
  153. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +45 -255
  154. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +33 -88
  155. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +25 -89
  156. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +64 -0
  157. package/stacks/blazor-azure/.morph/config/agents.json +879 -764
  158. package/stacks/blazor-azure/.morph/hooks/{pre-commit-tests.sh → pre-commit/tests-csharp.sh} +3 -2
  159. package/stacks/blazor-azure/.morph/templates/.gitkeep +0 -0
  160. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +41 -0
  161. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +24 -0
  162. package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +23 -0
  163. package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +221 -0
  164. package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +79 -0
  165. package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +529 -0
  166. package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +209 -0
  167. package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +227 -0
  168. package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +122 -0
  169. package/stacks/nextjs-supabase/.claude/commands/morph-status.md +86 -0
  170. package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +122 -0
  171. package/stacks/nextjs-supabase/.claude/settings.local.json +6 -0
  172. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +30 -150
  173. package/stacks/nextjs-supabase/.morph/config/agents.json +345 -345
  174. package/stacks/nextjs-supabase/.morph/hooks/pre-commit/tests-typescript.sh +61 -0
  175. package/stacks/nextjs-supabase/.morph/templates/.gitkeep +0 -0
  176. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +22 -0
  177. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +22 -0
  178. package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +35 -0
  179. package/stacks/nextjs-supabase/README.md +6 -15
  180. package/bin/render-template.js +0 -303
  181. package/bin/semantic-detect-agents.js +0 -247
  182. package/bin/validate-agents-skills.js +0 -257
  183. package/bin/validate-agents.js +0 -70
  184. package/bin/validate-phase.js +0 -263
  185. package/docs/examples.md +0 -328
  186. package/scripts/reorganize-skills.cjs +0 -175
  187. package/scripts/validate-agents-structure.cjs +0 -52
  188. package/scripts/validate-skills.cjs +0 -180
  189. package/src/commands/deploy.js +0 -780
  190. package/src/lib/continuous-validator.js +0 -421
  191. package/src/lib/decision-constraint-loader.js +0 -109
  192. package/src/lib/design-system-scaffolder.js +0 -299
  193. package/src/lib/hook-executor.js +0 -257
  194. package/src/lib/mockup-generator.js +0 -366
  195. package/src/lib/ui-detector.js +0 -350
  196. package/stacks/blazor-azure/.azure/README.md +0 -293
  197. package/stacks/blazor-azure/.azure/docs/azure-devops-setup.md +0 -454
  198. package/stacks/blazor-azure/.azure/docs/branch-strategy.md +0 -398
  199. package/stacks/blazor-azure/.azure/docs/local-development.md +0 -515
  200. package/stacks/blazor-azure/.azure/pipelines/pipeline-variables.yml +0 -34
  201. package/stacks/blazor-azure/.azure/pipelines/prod-pipeline.yml +0 -319
  202. package/stacks/blazor-azure/.azure/pipelines/staging-pipeline.yml +0 -234
  203. package/stacks/blazor-azure/.azure/pipelines/templates/build-dotnet.yml +0 -75
  204. package/stacks/blazor-azure/.azure/pipelines/templates/deploy-app-service.yml +0 -94
  205. package/stacks/blazor-azure/.azure/pipelines/templates/deploy-container-app.yml +0 -120
  206. package/stacks/blazor-azure/.azure/pipelines/templates/infra-deploy.yml +0 -90
  207. package/stacks/blazor-azure/.claude/settings.local.json +0 -15
  208. package/stacks/blazor-azure/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -392
  209. package/stacks/blazor-azure/.morph/docs/workflows/design-impl.md +0 -37
  210. package/stacks/blazor-azure/.morph/docs/workflows/enforcement-pipeline.md +0 -668
  211. package/stacks/blazor-azure/.morph/docs/workflows/fast-track.md +0 -29
  212. package/stacks/blazor-azure/.morph/docs/workflows/full-morph.md +0 -76
  213. package/stacks/blazor-azure/.morph/docs/workflows/standard.md +0 -44
  214. package/stacks/blazor-azure/.morph/docs/workflows/ui-refresh.md +0 -39
  215. package/stacks/blazor-azure/.morph/examples/api-nextjs/README.md +0 -241
  216. package/stacks/blazor-azure/.morph/examples/api-nextjs/contracts.ts +0 -307
  217. package/stacks/blazor-azure/.morph/examples/api-nextjs/spec.md +0 -399
  218. package/stacks/blazor-azure/.morph/examples/api-nextjs/tasks.md +0 -168
  219. package/stacks/blazor-azure/.morph/examples/micro-saas/README.md +0 -125
  220. package/stacks/blazor-azure/.morph/examples/micro-saas/contracts.cs +0 -358
  221. package/stacks/blazor-azure/.morph/examples/micro-saas/decisions.md +0 -246
  222. package/stacks/blazor-azure/.morph/examples/micro-saas/spec.md +0 -236
  223. package/stacks/blazor-azure/.morph/examples/micro-saas/tasks.md +0 -150
  224. package/stacks/blazor-azure/.morph/examples/multi-agent/README.md +0 -309
  225. package/stacks/blazor-azure/.morph/examples/multi-agent/contracts.cs +0 -433
  226. package/stacks/blazor-azure/.morph/examples/multi-agent/spec.md +0 -479
  227. package/stacks/blazor-azure/.morph/examples/multi-agent/tasks.md +0 -185
  228. package/stacks/blazor-azure/.morph/examples/scheduled-reports/decisions.md +0 -158
  229. package/stacks/blazor-azure/.morph/examples/scheduled-reports/proposal.md +0 -95
  230. package/stacks/blazor-azure/.morph/examples/scheduled-reports/spec.md +0 -267
  231. package/stacks/blazor-azure/.morph/examples/state-v3.json +0 -188
  232. package/stacks/blazor-azure/.morph/hooks/README.md +0 -348
  233. package/stacks/blazor-azure/.morph/hooks/pre-commit-agents.sh +0 -24
  234. package/stacks/blazor-azure/.morph/hooks/pre-commit-all.sh +0 -48
  235. package/stacks/blazor-azure/.morph/hooks/pre-commit-specs.sh +0 -49
  236. package/stacks/blazor-azure/.morph/hooks/task-completed.js +0 -73
  237. package/stacks/blazor-azure/.morph/hooks/teammate-idle.js +0 -68
  238. package/stacks/blazor-azure/.morph/standards/agent-framework-blazor-ui.md +0 -359
  239. package/stacks/blazor-azure/.morph/standards/agent-framework-production.md +0 -410
  240. package/stacks/blazor-azure/.morph/standards/agent-framework-setup.md +0 -413
  241. package/stacks/blazor-azure/.morph/standards/agent-framework-workflows.md +0 -349
  242. package/stacks/blazor-azure/.morph/standards/agent-teams-workflow.md +0 -474
  243. package/stacks/blazor-azure/.morph/standards/architecture.md +0 -325
  244. package/stacks/blazor-azure/.morph/standards/azure.md +0 -605
  245. package/stacks/blazor-azure/.morph/standards/coding.md +0 -377
  246. package/stacks/blazor-azure/.morph/standards/dotnet10-migration.md +0 -520
  247. package/stacks/blazor-azure/.morph/standards/fluent-ui-setup.md +0 -590
  248. package/stacks/blazor-azure/.morph/standards/migration-guide.md +0 -514
  249. package/stacks/blazor-azure/.morph/standards/passkeys-auth.md +0 -423
  250. package/stacks/blazor-azure/.morph/standards/vector-search-rag.md +0 -536
  251. package/stacks/blazor-azure/.morph/templates/CONTEXT-FEATURE.md +0 -276
  252. package/stacks/blazor-azure/.morph/templates/CONTEXT.md +0 -170
  253. package/stacks/blazor-azure/.morph/templates/FluentDesignTheme.cs +0 -149
  254. package/stacks/blazor-azure/.morph/templates/MudTheme.cs +0 -281
  255. package/stacks/blazor-azure/.morph/templates/agent.cs +0 -163
  256. package/stacks/blazor-azure/.morph/templates/clarify-questions.md +0 -159
  257. package/stacks/blazor-azure/.morph/templates/component.razor +0 -239
  258. package/stacks/blazor-azure/.morph/templates/contracts/Commands.cs +0 -74
  259. package/stacks/blazor-azure/.morph/templates/contracts/Entities.cs +0 -25
  260. package/stacks/blazor-azure/.morph/templates/contracts/Queries.cs +0 -74
  261. package/stacks/blazor-azure/.morph/templates/contracts/README.md +0 -74
  262. package/stacks/blazor-azure/.morph/templates/contracts.cs +0 -217
  263. package/stacks/blazor-azure/.morph/templates/decisions.md +0 -123
  264. package/stacks/blazor-azure/.morph/templates/design-system.css +0 -226
  265. package/stacks/blazor-azure/.morph/templates/infra/.dockerignore.example +0 -89
  266. package/stacks/blazor-azure/.morph/templates/infra/Dockerfile.example +0 -82
  267. package/stacks/blazor-azure/.morph/templates/infra/README.md +0 -286
  268. package/stacks/blazor-azure/.morph/templates/infra/app-insights.bicep +0 -63
  269. package/stacks/blazor-azure/.morph/templates/infra/app-service.bicep +0 -164
  270. package/stacks/blazor-azure/.morph/templates/infra/azure-pipelines-deploy.yml +0 -480
  271. package/stacks/blazor-azure/.morph/templates/infra/container-app-env.bicep +0 -49
  272. package/stacks/blazor-azure/.morph/templates/infra/container-app.bicep +0 -156
  273. package/stacks/blazor-azure/.morph/templates/infra/deploy-checklist.md +0 -426
  274. package/stacks/blazor-azure/.morph/templates/infra/deploy.ps1 +0 -229
  275. package/stacks/blazor-azure/.morph/templates/infra/deploy.sh +0 -208
  276. package/stacks/blazor-azure/.morph/templates/infra/key-vault.bicep +0 -91
  277. package/stacks/blazor-azure/.morph/templates/infra/main.bicep +0 -189
  278. package/stacks/blazor-azure/.morph/templates/infra/parameters.dev.json +0 -29
  279. package/stacks/blazor-azure/.morph/templates/infra/parameters.prod.json +0 -29
  280. package/stacks/blazor-azure/.morph/templates/infra/parameters.staging.json +0 -29
  281. package/stacks/blazor-azure/.morph/templates/infra/sql-database.bicep +0 -103
  282. package/stacks/blazor-azure/.morph/templates/infra/storage.bicep +0 -106
  283. package/stacks/blazor-azure/.morph/templates/integrations/asaas-client.cs +0 -387
  284. package/stacks/blazor-azure/.morph/templates/integrations/asaas-webhook.cs +0 -351
  285. package/stacks/blazor-azure/.morph/templates/integrations/azure-identity-config.cs +0 -288
  286. package/stacks/blazor-azure/.morph/templates/integrations/clerk-config.cs +0 -258
  287. package/stacks/blazor-azure/.morph/templates/job.cs +0 -171
  288. package/stacks/blazor-azure/.morph/templates/migration.cs +0 -83
  289. package/stacks/blazor-azure/.morph/templates/proposal.md +0 -141
  290. package/stacks/blazor-azure/.morph/templates/recap.md +0 -94
  291. package/stacks/blazor-azure/.morph/templates/repository.cs +0 -141
  292. package/stacks/blazor-azure/.morph/templates/saas/subscription.cs +0 -347
  293. package/stacks/blazor-azure/.morph/templates/saas/tenant.cs +0 -338
  294. package/stacks/blazor-azure/.morph/templates/service.cs +0 -139
  295. package/stacks/blazor-azure/.morph/templates/simulation.md +0 -353
  296. package/stacks/blazor-azure/.morph/templates/spec.md +0 -149
  297. package/stacks/blazor-azure/.morph/templates/sprint-status.yaml +0 -68
  298. package/stacks/blazor-azure/.morph/templates/state.template.json +0 -222
  299. package/stacks/blazor-azure/.morph/templates/story.md +0 -143
  300. package/stacks/blazor-azure/.morph/templates/tasks.md +0 -257
  301. package/stacks/blazor-azure/.morph/templates/test.cs +0 -239
  302. package/stacks/blazor-azure/.morph/templates/ui-components.md +0 -362
  303. package/stacks/blazor-azure/.morph/templates/ui-design-system.md +0 -286
  304. package/stacks/blazor-azure/.morph/templates/ui-flows.md +0 -336
  305. package/stacks/blazor-azure/.morph/templates/ui-mockups.md +0 -133
  306. package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +0 -169
  307. package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +0 -247
  308. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +0 -697
  309. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +0 -85
  310. package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +0 -86
  311. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +0 -498
  312. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +0 -121
  313. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +0 -138
  314. package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +0 -162
  315. package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +0 -191
  316. package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +0 -193
  317. package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +0 -171
  318. package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +0 -164
  319. package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +0 -179
  320. package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +0 -148
  321. package/stacks/nextjs-supabase/.morph/templates/contracts.cs +0 -173
  322. package/stacks/nextjs-supabase/.morph/templates/contracts.ts +0 -168
  323. package/stacks/nextjs-supabase/.morph/templates/decisions.md +0 -115
  324. package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +0 -38
  325. package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +0 -48
  326. package/stacks/nextjs-supabase/.morph/templates/proposal.md +0 -145
  327. package/stacks/nextjs-supabase/.morph/templates/recap.md +0 -134
  328. package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +0 -57
  329. package/stacks/nextjs-supabase/.morph/templates/spec.md +0 -231
  330. package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +0 -100
  331. package/stacks/nextjs-supabase/.morph/templates/tasks.md +0 -257
  332. /package/src/lib/{design-system-generator.js → generators/design-system-generator.js} +0 -0
  333. /package/src/lib/{learning-system.js → learning/learning-system.js} +0 -0
@@ -0,0 +1,188 @@
1
+ /**
2
+ * @fileoverview Wizard Questions - Defines interactive wizard questions
3
+ * @module morph-spec/ui/wizard-questions
4
+ */
5
+
6
+ /**
7
+ * Get wizard questions for interactive mode
8
+ * @returns {Array} Inquirer questions
9
+ */
10
+ export function getWizardQuestions() {
11
+ return [
12
+ {
13
+ type: 'input',
14
+ name: 'name',
15
+ message: '1/7 Project name:',
16
+ default: process.cwd().split(/[/\\]/).pop(),
17
+ validate: (input) => {
18
+ if (!input || input.trim().length === 0) {
19
+ return 'Project name is required';
20
+ }
21
+ return true;
22
+ }
23
+ },
24
+ {
25
+ type: 'input',
26
+ name: 'description',
27
+ message: '2/7 Project description (1-2 sentences):',
28
+ validate: (input) => {
29
+ if (!input || input.trim().length < 10) {
30
+ return 'Description must be at least 10 characters';
31
+ }
32
+ return true;
33
+ }
34
+ },
35
+ {
36
+ type: 'list',
37
+ name: 'type',
38
+ message: '3/7 Project type:',
39
+ choices: [
40
+ { name: 'Blazor Server (.NET)', value: 'blazor-server' },
41
+ { name: 'Next.js (React)', value: 'nextjs' },
42
+ { name: '.NET Web API', value: 'dotnet-api' },
43
+ { name: 'CLI Tool', value: 'cli-tool' },
44
+ { name: 'Monorepo (multiple projects)', value: 'monorepo' },
45
+ { name: 'Other', value: 'other' }
46
+ ]
47
+ },
48
+ {
49
+ type: 'list',
50
+ name: 'frontend',
51
+ message: '4/7 Frontend technology:',
52
+ choices: [
53
+ { name: 'Blazor Server', value: 'blazor' },
54
+ { name: 'Next.js', value: 'nextjs' },
55
+ { name: 'React', value: 'react' },
56
+ { name: 'Vue.js', value: 'vue' },
57
+ { name: 'Angular', value: 'angular' },
58
+ { name: 'None (backend-only)', value: null }
59
+ ],
60
+ when: (answers) => answers.type !== 'cli-tool' && answers.type !== 'dotnet-api'
61
+ },
62
+ {
63
+ type: 'list',
64
+ name: 'backend',
65
+ message: '5/7 Backend technology:',
66
+ choices: [
67
+ { name: '.NET 10', value: 'dotnet-10' },
68
+ { name: '.NET 9', value: 'dotnet-9' },
69
+ { name: '.NET 8', value: 'dotnet-8' },
70
+ { name: 'Node.js', value: 'nodejs' },
71
+ { name: 'Other', value: 'other' }
72
+ ],
73
+ default: 'dotnet-10'
74
+ },
75
+ {
76
+ type: 'list',
77
+ name: 'database',
78
+ message: '6/7 Database:',
79
+ choices: [
80
+ { name: 'Azure SQL Database', value: 'azure-sql' },
81
+ { name: 'PostgreSQL', value: 'postgresql' },
82
+ { name: 'Cosmos DB', value: 'cosmosdb' },
83
+ { name: 'MongoDB', value: 'mongodb' },
84
+ { name: 'SQLite', value: 'sqlite' },
85
+ { name: 'Supabase (PostgreSQL)', value: 'supabase' },
86
+ { name: 'None (no database)', value: null }
87
+ ]
88
+ },
89
+ {
90
+ type: 'confirm',
91
+ name: 'hasAzure',
92
+ message: '7a/7 Uses Azure infrastructure?',
93
+ default: false
94
+ },
95
+ {
96
+ type: 'confirm',
97
+ name: 'hasDocker',
98
+ message: '7b/7 Uses Docker containerization?',
99
+ default: true
100
+ }
101
+ ];
102
+ }
103
+
104
+ /**
105
+ * Map wizard answers to ProjectConfig
106
+ * @param {Object} answers - Wizard answers from inquirer
107
+ * @returns {ProjectConfig} Mapped project config
108
+ */
109
+ export function mapAnswersToConfig(answers) {
110
+ // Parse backend tech and version
111
+ const backendParts = answers.backend.split('-');
112
+ const backendTech = backendParts[0] === 'dotnet' ? '.NET' :
113
+ backendParts[0] === 'nodejs' ? 'Node.js' :
114
+ answers.backend;
115
+ const backendVersion = backendParts[1] || 'latest';
116
+
117
+ // Map frontend
118
+ let frontend = null;
119
+ if (answers.frontend) {
120
+ const frontendMap = {
121
+ 'blazor': { tech: 'Blazor', version: backendVersion, details: 'Blazor Server' },
122
+ 'nextjs': { tech: 'Next.js', version: '15', details: 'App Router' },
123
+ 'react': { tech: 'React', version: '18', details: null },
124
+ 'vue': { tech: 'Vue.js', version: '3', details: null },
125
+ 'angular': { tech: 'Angular', version: '17', details: null }
126
+ };
127
+ frontend = frontendMap[answers.frontend] || null;
128
+ }
129
+
130
+ // Map database
131
+ let database = null;
132
+ if (answers.database) {
133
+ const databaseMap = {
134
+ 'azure-sql': { tech: 'Azure SQL', version: 'latest', details: 'Managed SQL Database' },
135
+ 'postgresql': { tech: 'PostgreSQL', version: '16', details: null },
136
+ 'cosmosdb': { tech: 'Cosmos DB', version: 'latest', details: 'NoSQL' },
137
+ 'mongodb': { tech: 'MongoDB', version: '7', details: null },
138
+ 'sqlite': { tech: 'SQLite', version: '3', details: null },
139
+ 'supabase': { tech: 'PostgreSQL', version: '16', details: 'Managed by Supabase' }
140
+ };
141
+ database = databaseMap[answers.database] || null;
142
+ }
143
+
144
+ // Infer architecture from project type
145
+ const architectureMap = {
146
+ 'blazor-server': 'clean-architecture',
147
+ 'nextjs': 'layered',
148
+ 'dotnet-api': 'clean-architecture',
149
+ 'cli-tool': 'monolith',
150
+ 'monorepo': 'microservices',
151
+ 'other': 'layered'
152
+ };
153
+
154
+ const architecture = architectureMap[answers.type] || 'layered';
155
+
156
+ // Infer hosting
157
+ let hosting = null;
158
+ if (answers.hasAzure) {
159
+ hosting = 'Azure';
160
+ } else if (answers.hasDocker) {
161
+ hosting = 'Docker';
162
+ }
163
+
164
+ return {
165
+ name: answers.name,
166
+ description: answers.description,
167
+ type: answers.type,
168
+ stack: {
169
+ frontend,
170
+ backend: {
171
+ tech: backendTech,
172
+ version: backendVersion,
173
+ details: null
174
+ },
175
+ database,
176
+ hosting
177
+ },
178
+ architecture,
179
+ projectStructure: 'User-specified configuration via interactive wizard',
180
+ conventions: 'Standard conventions for ' + backendTech,
181
+ repository: null,
182
+ hasAzure: answers.hasAzure,
183
+ hasDocker: answers.hasDocker,
184
+ hasDevOps: false,
185
+ confidence: 100, // User input is 100% confident
186
+ warnings: ['Configuration was manually entered, not auto-detected']
187
+ };
188
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Unified color utilities for CLI output
3
+ *
4
+ * Replaces manual ANSI codes with consistent chalk usage.
5
+ * Standardizes color handling across the codebase.
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+
10
+ // Re-export chalk for direct usage
11
+ export { chalk };
12
+
13
+ /**
14
+ * Predefined color functions for common use cases
15
+ */
16
+ export const colors = {
17
+ error: chalk.red,
18
+ success: chalk.green,
19
+ warning: chalk.yellow,
20
+ info: chalk.blue,
21
+ dim: chalk.gray,
22
+ bold: chalk.bold,
23
+ highlight: chalk.cyan,
24
+ };
25
+
26
+ /**
27
+ * Status indicators with colors
28
+ */
29
+ export const status = {
30
+ success: chalk.green('✓'),
31
+ error: chalk.red('✗'),
32
+ warning: chalk.yellow('⚠'),
33
+ info: chalk.blue('ℹ'),
34
+ };
35
+
36
+ /**
37
+ * Format a success message
38
+ * @param {string} message - Message to format
39
+ * @returns {string} Formatted message
40
+ */
41
+ export function formatSuccess(message) {
42
+ return `${status.success} ${chalk.green(message)}`;
43
+ }
44
+
45
+ /**
46
+ * Format an error message
47
+ * @param {string} message - Message to format
48
+ * @returns {string} Formatted message
49
+ */
50
+ export function formatError(message) {
51
+ return `${status.error} ${chalk.red(message)}`;
52
+ }
53
+
54
+ /**
55
+ * Format a warning message
56
+ * @param {string} message - Message to format
57
+ * @returns {string} Formatted message
58
+ */
59
+ export function formatWarning(message) {
60
+ return `${status.warning} ${chalk.yellow(message)}`;
61
+ }
62
+
63
+ /**
64
+ * Format an info message
65
+ * @param {string} message - Message to format
66
+ * @returns {string} Formatted message
67
+ */
68
+ export function formatInfo(message) {
69
+ return `${status.info} ${chalk.blue(message)}`;
70
+ }
@@ -1,189 +1,188 @@
1
- import fs from 'fs-extra';
2
- import { join, dirname, resolve } from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { resolveStackPath } from '../lib/stack-resolver.js';
5
-
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const frameworkRoot = join(__dirname, '..', '..');
8
-
9
- function isSamePath(a, b) {
10
- return resolve(a) === resolve(b);
11
- }
12
-
13
- export function getContentDir() {
14
- return resolveStackPath(frameworkRoot);
15
- }
16
-
17
- export async function copyDirectory(src, dest, options = {}) {
18
- if (isSamePath(src, dest)) return;
19
-
20
- const { filter, overwrite = true } = options;
21
-
22
- await fs.copy(src, dest, {
23
- overwrite,
24
- filter: filter || (() => true),
25
- errorOnExist: false
26
- });
27
- }
28
-
29
- export async function copyFile(src, dest) {
30
- if (isSamePath(src, dest)) return;
31
-
32
- await fs.ensureDir(dirname(dest));
33
- await fs.copy(src, dest, { overwrite: true });
34
- }
35
-
36
- export async function pathExists(path) {
37
- return fs.pathExists(path);
38
- }
39
-
40
- export async function readJson(path) {
41
- return fs.readJson(path);
42
- }
43
-
44
- export async function writeJson(path, data) {
45
- await fs.ensureDir(dirname(path));
46
- await fs.writeJson(path, data, { spaces: 2 });
47
- }
48
-
49
- export async function ensureDir(path) {
50
- await fs.ensureDir(path);
51
- }
52
-
53
- export async function writeFile(path, content) {
54
- await fs.ensureDir(dirname(path));
55
- await fs.writeFile(path, content, 'utf8');
56
- }
57
-
58
- export async function removeDir(path) {
59
- await fs.remove(path);
60
- }
61
-
62
- export async function readFile(path) {
63
- return fs.readFile(path, 'utf8');
64
- }
65
-
66
- /**
67
- * Create symlink with fallback to copy if symlink fails
68
- * @param {string} target - Path to the original file/folder
69
- * @param {string} link - Path where symlink should be created
70
- * @param {string} type - 'file' or 'dir'
71
- * @returns {Promise<'symlink' | 'copy'>} - Returns how the link was created
72
- */
73
- export async function createSymlink(target, link, type = 'file') {
74
- await fs.ensureDir(dirname(link));
75
-
76
- try {
77
- // Try to create symlink
78
- await fs.ensureSymlink(target, link, type);
79
- return 'symlink';
80
- } catch (error) {
81
- // Fallback: copy the file/directory if symlink fails
82
- // (Windows may require admin permissions for symlinks)
83
- if (type === 'file') {
84
- await copyFile(target, link);
85
- } else {
86
- await copyDirectory(target, link);
87
- }
88
- return 'copy';
89
- }
90
- }
91
-
92
- /**
93
- * Create a directory link (junction on Windows, symlink on other platforms)
94
- * with fallback to directory copy if linking fails.
95
- * @param {string} target - Path to the original directory
96
- * @param {string} link - Path where the link should be created
97
- * @returns {Promise<'junction' | 'symlink' | 'copy'>} - How the link was created
98
- */
99
- export async function createDirectoryLink(target, link) {
100
- await fs.ensureDir(dirname(link));
101
-
102
- // Remove existing link/directory before recreating
103
- if (await pathExists(link)) {
104
- await fs.remove(link);
105
- }
106
-
107
- if (process.platform === 'win32') {
108
- try {
109
- // Junction on Windows - does NOT require admin privileges
110
- await fs.symlink(target, link, 'junction');
111
- return 'junction';
112
- } catch {
113
- try {
114
- await fs.ensureSymlink(target, link, 'dir');
115
- return 'symlink';
116
- } catch {
117
- await copyDirectory(target, link);
118
- return 'copy';
119
- }
120
- }
121
- } else {
122
- try {
123
- await fs.ensureSymlink(target, link, 'dir');
124
- return 'symlink';
125
- } catch {
126
- await copyDirectory(target, link);
127
- return 'copy';
128
- }
129
- }
130
- }
131
-
132
- export async function updateGitignore(projectPath) {
133
- const gitignorePath = join(projectPath, '.gitignore');
134
-
135
- const morphRules = [
136
- '',
137
- '# MORPH-SPEC',
138
- '.morph/examples/',
139
- '.morph/templates/',
140
- '.claude/settings.local.json',
141
- ''
142
- ];
143
-
144
- let content = '';
145
- let hasMorphSection = false;
146
-
147
- // Read existing .gitignore if it exists
148
- if (await pathExists(gitignorePath)) {
149
- content = await readFile(gitignorePath);
150
- hasMorphSection = content.includes('# MORPH-SPEC');
151
- }
152
-
153
- // If MORPH section already exists, check if rules are up to date
154
- if (hasMorphSection) {
155
- const lines = content.split('\n');
156
- const morphStartIndex = lines.findIndex(line => line.trim() === '# MORPH-SPEC');
157
-
158
- // Find the end of MORPH section (next empty line or section header)
159
- let morphEndIndex = morphStartIndex + 1;
160
- while (morphEndIndex < lines.length &&
161
- lines[morphEndIndex].trim() !== '' &&
162
- !lines[morphEndIndex].startsWith('#')) {
163
- morphEndIndex++;
164
- }
165
-
166
- // Extract current MORPH rules
167
- const currentMorphRules = lines.slice(morphStartIndex, morphEndIndex + 1);
168
- const expectedMorphRules = morphRules.slice(1, -1); // Remove empty lines from comparison
169
-
170
- // Check if all expected rules are present
171
- const missingRules = expectedMorphRules.filter(rule =>
172
- rule.startsWith('#') || !currentMorphRules.some(line => line.trim() === rule)
173
- );
174
-
175
- if (missingRules.length > 0) {
176
- // Update the section with all rules
177
- lines.splice(morphStartIndex, morphEndIndex - morphStartIndex, ...morphRules.slice(1, -1));
178
- content = lines.join('\n');
179
- }
180
- } else {
181
- // Add MORPH section
182
- if (content && !content.endsWith('\n')) {
183
- content += '\n';
184
- }
185
- content += morphRules.join('\n');
186
- }
187
-
188
- await writeFile(gitignorePath, content);
189
- }
1
+ import fs from 'fs-extra';
2
+ import { join, dirname, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { resolveStackPath } from '../lib/stacks/stack-resolver.js';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const frameworkRoot = join(__dirname, '..', '..');
8
+
9
+ function isSamePath(a, b) {
10
+ return resolve(a) === resolve(b);
11
+ }
12
+
13
+ export function getContentDir() {
14
+ return resolveStackPath(frameworkRoot);
15
+ }
16
+
17
+ export async function copyDirectory(src, dest, options = {}) {
18
+ if (isSamePath(src, dest)) return;
19
+
20
+ const { filter, overwrite = true } = options;
21
+
22
+ await fs.copy(src, dest, {
23
+ overwrite,
24
+ filter: filter || (() => true),
25
+ errorOnExist: false
26
+ });
27
+ }
28
+
29
+ export async function copyFile(src, dest) {
30
+ if (isSamePath(src, dest)) return;
31
+
32
+ await fs.ensureDir(dirname(dest));
33
+ await fs.copy(src, dest, { overwrite: true });
34
+ }
35
+
36
+ export async function pathExists(path) {
37
+ return fs.pathExists(path);
38
+ }
39
+
40
+ export async function readJson(path) {
41
+ return fs.readJson(path);
42
+ }
43
+
44
+ export async function writeJson(path, data) {
45
+ await fs.ensureDir(dirname(path));
46
+ await fs.writeJson(path, data, { spaces: 2 });
47
+ }
48
+
49
+ export async function ensureDir(path) {
50
+ await fs.ensureDir(path);
51
+ }
52
+
53
+ export async function writeFile(path, content) {
54
+ await fs.ensureDir(dirname(path));
55
+ await fs.writeFile(path, content, 'utf8');
56
+ }
57
+
58
+ export async function removeDir(path) {
59
+ await fs.remove(path);
60
+ }
61
+
62
+ export async function readFile(path) {
63
+ return fs.readFile(path, 'utf8');
64
+ }
65
+
66
+ /**
67
+ * Create symlink with fallback to copy if symlink fails
68
+ * @param {string} target - Path to the original file/folder
69
+ * @param {string} link - Path where symlink should be created
70
+ * @param {string} type - 'file' or 'dir'
71
+ * @returns {Promise<'symlink' | 'copy'>} - Returns how the link was created
72
+ */
73
+ export async function createSymlink(target, link, type = 'file') {
74
+ await fs.ensureDir(dirname(link));
75
+
76
+ try {
77
+ // Try to create symlink
78
+ await fs.ensureSymlink(target, link, type);
79
+ return 'symlink';
80
+ } catch (error) {
81
+ // Fallback: copy the file/directory if symlink fails
82
+ // (Windows may require admin permissions for symlinks)
83
+ if (type === 'file') {
84
+ await copyFile(target, link);
85
+ } else {
86
+ await copyDirectory(target, link);
87
+ }
88
+ return 'copy';
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Create a directory link (junction on Windows, symlink on other platforms)
94
+ * with fallback to directory copy if linking fails.
95
+ * @param {string} target - Path to the original directory
96
+ * @param {string} link - Path where the link should be created
97
+ * @returns {Promise<'junction' | 'symlink' | 'copy'>} - How the link was created
98
+ */
99
+ export async function createDirectoryLink(target, link) {
100
+ await fs.ensureDir(dirname(link));
101
+
102
+ // Remove existing link/directory before recreating
103
+ if (await pathExists(link)) {
104
+ await fs.remove(link);
105
+ }
106
+
107
+ if (process.platform === 'win32') {
108
+ try {
109
+ // Junction on Windows - does NOT require admin privileges
110
+ await fs.symlink(target, link, 'junction');
111
+ return 'junction';
112
+ } catch {
113
+ try {
114
+ await fs.ensureSymlink(target, link, 'dir');
115
+ return 'symlink';
116
+ } catch {
117
+ await copyDirectory(target, link);
118
+ return 'copy';
119
+ }
120
+ }
121
+ } else {
122
+ try {
123
+ await fs.ensureSymlink(target, link, 'dir');
124
+ return 'symlink';
125
+ } catch {
126
+ await copyDirectory(target, link);
127
+ return 'copy';
128
+ }
129
+ }
130
+ }
131
+
132
+ export async function updateGitignore(projectPath) {
133
+ const gitignorePath = join(projectPath, '.gitignore');
134
+
135
+ const morphRules = [
136
+ '',
137
+ '# MORPH-SPEC',
138
+ '.morph/templates/',
139
+ '.claude/settings.local.json',
140
+ ''
141
+ ];
142
+
143
+ let content = '';
144
+ let hasMorphSection = false;
145
+
146
+ // Read existing .gitignore if it exists
147
+ if (await pathExists(gitignorePath)) {
148
+ content = await readFile(gitignorePath);
149
+ hasMorphSection = content.includes('# MORPH-SPEC');
150
+ }
151
+
152
+ // If MORPH section already exists, check if rules are up to date
153
+ if (hasMorphSection) {
154
+ const lines = content.split('\n');
155
+ const morphStartIndex = lines.findIndex(line => line.trim() === '# MORPH-SPEC');
156
+
157
+ // Find the end of MORPH section (next empty line or section header)
158
+ let morphEndIndex = morphStartIndex + 1;
159
+ while (morphEndIndex < lines.length &&
160
+ lines[morphEndIndex].trim() !== '' &&
161
+ !lines[morphEndIndex].startsWith('#')) {
162
+ morphEndIndex++;
163
+ }
164
+
165
+ // Extract current MORPH rules
166
+ const currentMorphRules = lines.slice(morphStartIndex, morphEndIndex + 1);
167
+ const expectedMorphRules = morphRules.slice(1, -1); // Remove empty lines from comparison
168
+
169
+ // Check if all expected rules are present
170
+ const missingRules = expectedMorphRules.filter(rule =>
171
+ rule.startsWith('#') || !currentMorphRules.some(line => line.trim() === rule)
172
+ );
173
+
174
+ if (missingRules.length > 0) {
175
+ // Update the section with all rules
176
+ lines.splice(morphStartIndex, morphEndIndex - morphStartIndex, ...morphRules.slice(1, -1));
177
+ content = lines.join('\n');
178
+ }
179
+ } else {
180
+ // Add MORPH section
181
+ if (content && !content.endsWith('\n')) {
182
+ content += '\n';
183
+ }
184
+ content += morphRules.join('\n');
185
+ }
186
+
187
+ await writeFile(gitignorePath, content);
188
+ }