@polymorphism-tech/morph-spec 4.3.2 → 4.3.4
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.
- package/.morph/analytics/threads-log.jsonl +9 -0
- package/{stacks/blazor-azure/.morph → .morph}/config/config.json +9 -9
- package/.morph/state.json +48 -0
- package/bin/detect-agents.js +1 -2
- package/bin/morph-spec.js +2 -15
- package/{stacks/nextjs-supabase/.morph/config → framework}/agents.json +948 -948
- package/{stacks/nextjs-supabase/.claude → framework}/commands/morph-infra.md +1 -1
- package/framework/hooks/README.md +282 -0
- package/framework/hooks/agent-stop/validate-and-continue.js +96 -0
- package/framework/hooks/agent-stop/validate-checkpoints.js +101 -0
- package/framework/hooks/agent-stop/validate-tests.js +109 -0
- package/framework/hooks/agent-teams/dispatch.js +67 -0
- package/framework/hooks/agent-teams/phase-advanced.js +80 -0
- package/framework/hooks/agent-teams/task-completed.js +76 -0
- package/framework/hooks/agent-teams/teammate-idle.js +70 -0
- package/framework/hooks/commit-msg/conventional-commits.sh +33 -0
- package/framework/hooks/pre-commit/agents.sh +25 -0
- package/framework/hooks/pre-commit/orchestrator.sh +64 -0
- package/framework/hooks/pre-commit/specs.sh +50 -0
- package/framework/hooks/pre-push/run-tests.sh +44 -0
- package/framework/index/troubleshooting-index.json +184 -0
- package/framework/memory/patterns-learned.md +766 -0
- package/framework/skills/level-0-meta/README.md +7 -0
- package/framework/skills/level-0-meta/code-review.md +226 -0
- package/framework/skills/level-0-meta/morph-checklist.md +117 -0
- package/framework/skills/level-0-meta/simulation-checklist.md +77 -0
- package/framework/skills/level-1-workflows/README.md +7 -0
- package/framework/skills/level-1-workflows/morph-replicate.md +213 -0
- package/framework/skills/level-1-workflows/phase-clarify.md +131 -0
- package/framework/skills/level-1-workflows/phase-design.md +213 -0
- package/framework/skills/level-1-workflows/phase-setup.md +106 -0
- package/framework/skills/level-1-workflows/phase-tasks.md +164 -0
- package/framework/skills/level-1-workflows/phase-uiux.md +169 -0
- package/framework/skills/level-2-domains/README.md +14 -0
- package/framework/skills/level-2-domains/ai-agents/ai-system-architect.md +192 -0
- package/framework/skills/level-2-domains/architecture/po-pm-advisor.md +197 -0
- package/framework/skills/level-2-domains/architecture/prompt-engineer.md +189 -0
- package/framework/skills/level-2-domains/architecture/seo-growth-hacker.md +320 -0
- package/framework/skills/level-2-domains/architecture/standards-architect.md +156 -0
- package/framework/skills/level-2-domains/backend/api-designer.md +59 -0
- package/framework/skills/level-2-domains/backend/dotnet-senior.md +77 -0
- package/framework/skills/level-2-domains/backend/ef-modeler.md +58 -0
- package/framework/skills/level-2-domains/backend/hangfire-orchestrator.md +126 -0
- package/framework/skills/level-2-domains/backend/ms-agent-expert.md +45 -0
- package/framework/skills/level-2-domains/frontend/blazor-builder.md +210 -0
- package/framework/skills/level-2-domains/frontend/nextjs-expert.md +154 -0
- package/framework/skills/level-2-domains/frontend/ui-ux-designer.md +191 -0
- package/framework/skills/level-2-domains/infrastructure/azure-architect.md +142 -0
- package/framework/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +699 -0
- package/framework/skills/level-2-domains/infrastructure/bicep-architect.md +126 -0
- package/framework/skills/level-2-domains/infrastructure/container-specialist.md +131 -0
- package/framework/skills/level-2-domains/infrastructure/devops-engineer.md +119 -0
- package/framework/skills/level-2-domains/integrations/asaas-financial.md +130 -0
- package/framework/skills/level-2-domains/integrations/azure-identity.md +142 -0
- package/framework/skills/level-2-domains/integrations/clerk-auth.md +108 -0
- package/framework/skills/level-2-domains/integrations/hangfire-orchestrator.md +64 -0
- package/framework/skills/level-2-domains/integrations/resend-email.md +119 -0
- package/framework/skills/level-2-domains/quality/code-analyzer.md +235 -0
- package/framework/skills/level-2-domains/quality/testing-specialist.md +126 -0
- package/framework/skills/level-3-technologies/README.md +7 -0
- package/framework/skills/level-4-patterns/README.md +7 -0
- package/framework/squad-templates/backend-only.json +34 -0
- package/framework/squad-templates/frontend-only.json +34 -0
- package/framework/squad-templates/full-stack.json +52 -0
- package/framework/templates/.idea/morph-templates.xml +92 -0
- package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/framework/templates/IDE-SNIPPETS.md +266 -0
- package/framework/templates/README.md +814 -0
- package/framework/templates/REGISTRY.json +1677 -0
- package/framework/templates/code/dotnet/backend/repository.cs +141 -0
- package/framework/templates/code/dotnet/backend/service.cs +139 -0
- package/framework/templates/code/dotnet/contracts/Commands.cs +74 -0
- package/framework/templates/code/dotnet/contracts/Entities.cs +25 -0
- package/framework/templates/code/dotnet/contracts/Queries.cs +74 -0
- package/framework/templates/code/dotnet/contracts/README.md +74 -0
- package/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -0
- package/framework/templates/code/dotnet/contracts/contracts.cs +217 -0
- package/framework/templates/code/dotnet/database/migration.cs +83 -0
- package/framework/templates/code/dotnet/frontend/component.razor +239 -0
- package/framework/templates/code/dotnet/jobs/agent.cs +163 -0
- package/framework/templates/code/dotnet/jobs/job.cs +171 -0
- package/framework/templates/code/dotnet/test.cs +239 -0
- package/framework/templates/code/sql/rls-policy.sql +57 -0
- package/framework/templates/code/sql/supabase-migration.sql +100 -0
- package/framework/templates/code/sql/supabase-migration.template.sql +113 -0
- package/framework/templates/code/typescript/contracts.ts +168 -0
- package/framework/templates/context/CONTEXT-FEATURE.md +276 -0
- package/framework/templates/context/CONTEXT.md +181 -0
- package/framework/templates/docs/proposal.md +182 -0
- package/framework/templates/docs/spec.md +149 -0
- package/framework/templates/examples/design-system-examples.md +357 -0
- package/framework/templates/examples/spec-examples.md +90 -0
- package/framework/templates/feature/decisions.md +187 -0
- package/framework/templates/feature/recap.md +146 -0
- package/framework/templates/feature/tasks.md +199 -0
- package/framework/templates/infrastructure/azure/Dockerfile.example +82 -0
- package/framework/templates/infrastructure/azure/README.md +286 -0
- package/framework/templates/infrastructure/azure/app-insights.bicep +63 -0
- package/framework/templates/infrastructure/azure/app-service.bicep +164 -0
- package/framework/templates/infrastructure/azure/container-app-env.bicep +49 -0
- package/framework/templates/infrastructure/azure/container-app.bicep +156 -0
- package/framework/templates/infrastructure/azure/deploy-checklist.md +426 -0
- package/framework/templates/infrastructure/azure/deploy.ps1 +229 -0
- package/framework/templates/infrastructure/azure/deploy.sh +208 -0
- package/framework/templates/infrastructure/azure/key-vault.bicep +91 -0
- package/framework/templates/infrastructure/azure/main.bicep +189 -0
- package/framework/templates/infrastructure/azure/parameters.dev.json +29 -0
- package/framework/templates/infrastructure/azure/parameters.prod.json +29 -0
- package/framework/templates/infrastructure/azure/parameters.staging.json +29 -0
- package/framework/templates/infrastructure/azure/sql-database.bicep +103 -0
- package/framework/templates/infrastructure/azure/storage.bicep +106 -0
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -0
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -0
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
- package/framework/templates/infrastructure/docker/easypanel.template.json +54 -0
- package/framework/templates/infrastructure/github/README.md +593 -0
- package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
- package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
- package/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
- package/framework/templates/integrations/asaas-client.cs +387 -0
- package/framework/templates/integrations/asaas-webhook.cs +351 -0
- package/framework/templates/integrations/azure-identity-config.cs +288 -0
- package/framework/templates/integrations/clerk-config.cs +258 -0
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -0
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
- package/framework/templates/meta-prompts/hops/hop-retry.md +78 -0
- package/framework/templates/meta-prompts/hops/hop-validation.md +97 -0
- package/framework/templates/meta-prompts/hops/hop-wrapper.md +36 -0
- package/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
- package/framework/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
- package/framework/templates/saas/subscription.cs +347 -0
- package/framework/templates/saas/tenant.cs +338 -0
- package/framework/templates/state.template.json +17 -0
- package/framework/templates/ui/FluentDesignTheme.cs +149 -0
- package/framework/templates/ui/MudTheme.cs +281 -0
- package/framework/templates/ui/design-system.css +226 -0
- package/framework/workflows/README.md +1041 -0
- package/framework/workflows/configs/design-impl.json +49 -0
- package/framework/workflows/configs/fast-track.json +42 -0
- package/framework/workflows/configs/full-morph.json +79 -0
- package/framework/workflows/configs/fusion.json +39 -0
- package/framework/workflows/configs/long-running.json +33 -0
- package/framework/workflows/configs/standard.json +60 -0
- package/framework/workflows/configs/ui-refresh.json +49 -0
- package/framework/workflows/configs/zero-touch.json +75 -0
- package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -0
- package/framework/workflows/docs/design-impl.md +37 -0
- package/framework/workflows/docs/enforcement-pipeline.md +668 -0
- package/framework/workflows/docs/fast-track.md +29 -0
- package/framework/workflows/docs/full-morph.md +76 -0
- package/framework/workflows/docs/standard.md +44 -0
- package/framework/workflows/docs/ui-refresh.md +39 -0
- package/package.json +3 -3
- package/src/commands/feature/create-story.js +11 -7
- package/src/commands/project/detect-agents.js +1 -2
- package/src/commands/project/init.js +78 -31
- package/src/commands/project/update.js +9 -5
- package/src/commands/templates/template-customize.js +3 -17
- package/src/commands/templates/template-list.js +1 -15
- package/src/commands/templates/template-render.js +2 -3
- package/src/commands/templates/template-show.js +3 -5
- package/src/core/templates/template-registry.js +9 -23
- package/src/lib/detectors/structure-detector.js +3 -3
- package/src/lib/generators/context-generator.js +18 -6
- package/src/lib/hooks/hook-executor.js +0 -2
- package/src/lib/orchestration/team-orchestrator.js +1 -2
- package/src/lib/standards/standards-context-injector.js +3 -4
- package/src/lib/troubleshooting/troubleshoot-grep.js +3 -9
- package/src/lib/validators/validation-runner.js +1 -2
- package/src/utils/file-copier.js +1 -2
- package/docs/README.md +0 -144
- package/docs/api/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -978
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -1049
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/api/scripts/collapse.js +0 -39
- package/docs/api/scripts/commonNav.js +0 -28
- package/docs/api/scripts/linenumber.js +0 -25
- package/docs/api/scripts/nav.js +0 -12
- package/docs/api/scripts/polyfill.js +0 -4
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/api/scripts/prettify/lang-css.js +0 -2
- package/docs/api/scripts/prettify/prettify.js +0 -28
- package/docs/api/scripts/search.js +0 -99
- package/docs/api/styles/jsdoc.css +0 -776
- package/docs/api/styles/prettify.css +0 -80
- package/docs/cli-auto-detection.md +0 -219
- package/docs/getting-started.md +0 -296
- package/docs/installation.md +0 -361
- package/docs/next-generation/AGENTS.md +0 -521
- package/docs/next-generation/ANALYSIS.md +0 -555
- package/docs/next-generation/ARCHITECTURE.md +0 -436
- package/docs/next-generation/CONTEXT-OPTIMIZATION.md +0 -267
- package/docs/next-generation/EXECUTION-FLOW.md +0 -274
- package/docs/next-generation/FEATURES.md +0 -688
- package/docs/next-generation/META-PROMPTS.md +0 -235
- package/docs/next-generation/MIGRATION-GUIDE.md +0 -253
- package/docs/next-generation/README.md +0 -231
- package/docs/next-generation/ROADMAP.md +0 -801
- package/docs/next-generation/THREAD-MANAGEMENT.md +0 -240
- package/docs/templates.md +0 -418
- package/docs/troubleshooting.md +0 -269
- package/docs/validation-checklist.md +0 -264
- package/scripts/postinstall.js +0 -132
- package/src/lib/stacks/index.js +0 -7
- package/src/lib/stacks/stack-resolver.js +0 -180
- package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
- package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
- package/stacks/blazor-azure/.morph/.morphversion +0 -5
- package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/config/agents.json +0 -948
- package/stacks/blazor-azure/.morph/config/config.template.json +0 -122
- package/stacks/blazor-azure/.morph/features/.gitkeep +0 -25
- package/stacks/blazor-azure/.morph/hooks/pre-commit/tests-csharp.sh +0 -61
- package/stacks/blazor-azure/.morph/project/context/README.md +0 -17
- package/stacks/blazor-azure/.morph/project.md +0 -160
- package/stacks/blazor-azure/.morph/schemas/agent.schema.json +0 -296
- package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
- package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
- package/stacks/blazor-azure/.morph/state.json +0 -18
- package/stacks/blazor-azure/.morph/test-infra/example.bicep +0 -59
- package/stacks/blazor-azure/CLAUDE.md +0 -155
- package/stacks/blazor-azure/README.md +0 -79
- package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +0 -221
- package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +0 -79
- package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +0 -529
- package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +0 -227
- package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +0 -122
- package/stacks/nextjs-supabase/.claude/commands/morph-status.md +0 -86
- package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/nextjs-supabase/.morph/.morphversion +0 -5
- package/stacks/nextjs-supabase/.morph/config/config.json +0 -9
- package/stacks/nextjs-supabase/.morph/config/config.template.json +0 -92
- package/stacks/nextjs-supabase/.morph/hooks/pre-commit/tests-typescript.sh +0 -61
- package/stacks/nextjs-supabase/.morph/project/context/README.md +0 -17
- package/stacks/nextjs-supabase/.morph/project.md +0 -168
- package/stacks/nextjs-supabase/.morph/standards/ai-agents/blazor-ui.md +0 -364
- package/stacks/nextjs-supabase/.morph/standards/ai-agents/production.md +0 -415
- package/stacks/nextjs-supabase/.morph/standards/ai-agents/setup.md +0 -418
- package/stacks/nextjs-supabase/.morph/standards/ai-agents/team-orchestration.md +0 -479
- package/stacks/nextjs-supabase/.morph/standards/ai-agents/workflows.md +0 -354
- package/stacks/nextjs-supabase/.morph/standards/architecture/ddd/aggregates.md +0 -120
- package/stacks/nextjs-supabase/.morph/standards/architecture/ddd/entities.md +0 -99
- package/stacks/nextjs-supabase/.morph/standards/architecture/ddd/value-objects.md +0 -124
- package/stacks/nextjs-supabase/.morph/standards/backend/api/minimal-api.md +0 -494
- package/stacks/nextjs-supabase/.morph/standards/backend/api/rest.md +0 -492
- package/stacks/nextjs-supabase/.morph/standards/backend/api/validation.md +0 -88
- package/stacks/nextjs-supabase/.morph/standards/backend/authentication/passkeys.md +0 -428
- package/stacks/nextjs-supabase/.morph/standards/backend/database/ef-core.md +0 -199
- package/stacks/nextjs-supabase/.morph/standards/backend/database/migrations.md +0 -393
- package/stacks/nextjs-supabase/.morph/standards/backend/database/postgresql/database.md +0 -352
- package/stacks/nextjs-supabase/.morph/standards/backend/database/repository-patterns.md +0 -528
- package/stacks/nextjs-supabase/.morph/standards/backend/database/vector-search-rag.md +0 -541
- package/stacks/nextjs-supabase/.morph/standards/backend/dotnet/async.md +0 -366
- package/stacks/nextjs-supabase/.morph/standards/backend/dotnet/core.md +0 -117
- package/stacks/nextjs-supabase/.morph/standards/backend/dotnet/di.md +0 -439
- package/stacks/nextjs-supabase/.morph/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/stacks/nextjs-supabase/.morph/standards/backend/integrations/asaas/asaas-api.md +0 -216
- package/stacks/nextjs-supabase/.morph/standards/backend/integrations/clerk/clerk-auth.md +0 -290
- package/stacks/nextjs-supabase/.morph/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
- package/stacks/nextjs-supabase/.morph/standards/backend/integrations/resend/resend-email.md +0 -385
- package/stacks/nextjs-supabase/.morph/standards/context/analytics.md +0 -96
- package/stacks/nextjs-supabase/.morph/standards/context/bundles.md +0 -110
- package/stacks/nextjs-supabase/.morph/standards/context/priming.md +0 -78
- package/stacks/nextjs-supabase/.morph/standards/core/architecture.md +0 -185
- package/stacks/nextjs-supabase/.morph/standards/core/coding.md +0 -214
- package/stacks/nextjs-supabase/.morph/standards/core/git-branching-strategy.md +0 -403
- package/stacks/nextjs-supabase/.morph/standards/core/git.md +0 -185
- package/stacks/nextjs-supabase/.morph/standards/core/testing.md +0 -295
- package/stacks/nextjs-supabase/.morph/standards/data/nosql/blob-storage.md +0 -102
- package/stacks/nextjs-supabase/.morph/standards/data/nosql/cache/redis.md +0 -97
- package/stacks/nextjs-supabase/.morph/standards/data/nosql/cosmos-db.md +0 -118
- package/stacks/nextjs-supabase/.morph/standards/data/vector-search/azure-ai-search.md +0 -121
- package/stacks/nextjs-supabase/.morph/standards/data/vector-search/rag-chunking.md +0 -104
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/design-checklist.md +0 -222
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/fluent-ui.md +0 -137
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/html-conversion.md +0 -184
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/lifecycle.md +0 -195
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/pitfalls.md +0 -198
- package/stacks/nextjs-supabase/.morph/standards/frontend/blazor/state.md +0 -191
- package/stacks/nextjs-supabase/.morph/standards/frontend/design-system/animations.md +0 -151
- package/stacks/nextjs-supabase/.morph/standards/frontend/design-system/naming.md +0 -64
- package/stacks/nextjs-supabase/.morph/standards/frontend/nextjs/nextjs-patterns.md +0 -198
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/azure.md +0 -624
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/services/functions.md +0 -486
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/azure/services/storage.md +0 -407
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/docker/easypanel-deploy.md +0 -196
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/supabase/mcp-setup.md +0 -252
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/stacks/nextjs-supabase/.morph/standards/infrastructure/supabase/supabase-storage.md +0 -153
- package/stacks/nextjs-supabase/.morph/standards/integration/api/graphql.md +0 -91
- package/stacks/nextjs-supabase/.morph/standards/integration/api/grpc.md +0 -114
- package/stacks/nextjs-supabase/.morph/standards/integration/api/rest-design.md +0 -95
- package/stacks/nextjs-supabase/.morph/standards/integration/event-driven/cqrs.md +0 -101
- package/stacks/nextjs-supabase/.morph/standards/integration/event-driven/event-sourcing.md +0 -124
- package/stacks/nextjs-supabase/.morph/standards/integration/event-driven/service-bus.md +0 -95
- package/stacks/nextjs-supabase/.morph/standards/observability/logging.md +0 -131
- package/stacks/nextjs-supabase/.morph/standards/observability/metrics.md +0 -121
- package/stacks/nextjs-supabase/.morph/standards/observability/monitoring.md +0 -114
- package/stacks/nextjs-supabase/.morph/standards/observability/tracing.md +0 -132
- package/stacks/nextjs-supabase/.morph/standards/workflows/parallel-execution.md +0 -112
- package/stacks/nextjs-supabase/.morph/standards/workflows/thread-management.md +0 -113
- package/stacks/nextjs-supabase/CLAUDE.md +0 -155
- package/stacks/nextjs-supabase/README.md +0 -103
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-apply.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-archive.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-preflight.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-proposal.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-status.md +0 -0
- /package/{stacks/blazor-azure/.claude → framework}/commands/morph-troubleshoot.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/ai-agents/blazor-ui.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/ai-agents/production.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/ai-agents/setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/ai-agents/team-orchestration.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/ai-agents/workflows.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/architecture/ddd/aggregates.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/architecture/ddd/entities.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/architecture/ddd/value-objects.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/api/minimal-api.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/api/rest.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/api/validation.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/authentication/passkeys.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/database/ef-core.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/database/migrations.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/database/postgresql/database.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/database/repository-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/database/vector-search-rag.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/dotnet/async.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/dotnet/core.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/dotnet/di.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/dotnet/program-cs-checklist.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/integrations/asaas/asaas-api.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/integrations/clerk/clerk-auth.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/backend/integrations/resend/resend-email.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/context/analytics.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/context/bundles.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/context/priming.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/core/architecture.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/core/coding.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/core/git-branching-strategy.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/core/git.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/core/testing.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/data/nosql/blob-storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/data/nosql/cache/redis.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/data/nosql/cosmos-db.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/data/vector-search/azure-ai-search.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/data/vector-search/rag-chunking.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/design-checklist.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/fluent-ui-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/fluent-ui.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/html-conversion.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/lifecycle.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/pitfalls.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/blazor/state.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/design-system/animations.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/design-system/naming.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/frontend/nextjs/nextjs-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/azure.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/devops/local-development.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/services/functions.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/services/service-bus.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/azure/services/storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/docker/easypanel-deploy.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/supabase/mcp-setup.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/supabase/supabase-auth.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/supabase/supabase-pgvector.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/supabase/supabase-rls.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/infrastructure/supabase/supabase-storage.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/api/graphql.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/api/grpc.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/api/rest-design.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/event-driven/cqrs.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/event-driven/event-sourcing.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/integration/event-driven/service-bus.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/observability/logging.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/observability/metrics.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/observability/monitoring.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/observability/tracing.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/workflows/parallel-execution.md +0 -0
- /package/{stacks/blazor-azure/.morph → framework}/standards/workflows/thread-management.md +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Workflow: FULL MORPH (Alta Complexidade)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** sistema, autenticação, integração, pattern, cqrs, subsistema
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- > 10 arquivos, > 500 linhas, múltiplos componentes novos
|
|
8
|
+
- Infraestrutura Azure (Bicep), decisões arquiteturais estratégicas
|
|
9
|
+
|
|
10
|
+
## Fases (TODAS obrigatórias)
|
|
11
|
+
|
|
12
|
+
### FASE 0.5: CONTEXT (automática)
|
|
13
|
+
1. Detectar framework MORPH (`@polymorphism-tech/morph-spec`)
|
|
14
|
+
2. Detectar/criar estrutura `.morph/project/`
|
|
15
|
+
3. Análise automática: stack (glob patterns), arquitetura (pastas), configs, UI library
|
|
16
|
+
4. Analisar histórico: decisions.md passados, preferências do usuário
|
|
17
|
+
5. Gerar/atualizar `.morph/project/standards/inferred.md`
|
|
18
|
+
6. Ativar agentes baseado em stack + keywords
|
|
19
|
+
|
|
20
|
+
### FASE 0: PROPOSAL
|
|
21
|
+
1. `npx morph-spec detect "{user-request}"`
|
|
22
|
+
2. Analisar solicitação, identificar stack, estimar complexidade
|
|
23
|
+
3. Gerar proposal.md, registrar agentes no state.json
|
|
24
|
+
- **⛔ PAUSA:** 3 itens (1 ação + 1 pergunta + 1 sugestão)
|
|
25
|
+
|
|
26
|
+
### FASE 1: SETUP
|
|
27
|
+
1. Ler `.morph/config.json`
|
|
28
|
+
2. Confirmar stack, ativar agentes, criar pasta outputs
|
|
29
|
+
3. Carregar padrões (framework/standards/ > project/standards/)
|
|
30
|
+
|
|
31
|
+
### FASE 1.5: UI/UX (condicional - se keywords UI detectadas)
|
|
32
|
+
1. **Perguntar ao usuário:** layout, referências visuais, fluxo, imagens
|
|
33
|
+
2. Analisar referências fornecidas
|
|
34
|
+
3. Gerar deliverables AGNÓSTICOS de biblioteca (ui-mockups, ui-components, ui-flows)
|
|
35
|
+
4. Validar acessibilidade (WCAG 2.1) e responsividade
|
|
36
|
+
- **⛔ PAUSA:** Aprovar / Ajustar wireframes / Adicionar fluxos
|
|
37
|
+
|
|
38
|
+
### FASE 2: DESIGN
|
|
39
|
+
1. Gerar spec.md com requisitos completos
|
|
40
|
+
2. **DECISION POINTS** (cada um requer aprovação):
|
|
41
|
+
- Biblioteca UI (Fluent UI vs MudBlazor)
|
|
42
|
+
- Padrões Arquiteturais (CQRS vs simples, Repository vs EF direto)
|
|
43
|
+
- Estrutura de Dados (entidades, relacionamentos)
|
|
44
|
+
- Infraestrutura Azure (recursos, SKUs, custos)
|
|
45
|
+
- Bibliotecas/SDKs (NuGet packages)
|
|
46
|
+
3. Gerar contracts.cs, documentar decisões em decisions.md
|
|
47
|
+
- **⛔ PAUSA:** Aprovar / Ajustar escopo / Modificar contracts
|
|
48
|
+
|
|
49
|
+
### FASE 3: CLARIFY
|
|
50
|
+
1. Identificar ambiguidades, fazer perguntas, documentar em spec.md, validar edge cases
|
|
51
|
+
|
|
52
|
+
### FASE 4: TASKS
|
|
53
|
+
1. Quebrar spec em tasks T001-TXXX, definir ordem, checkpoints, dependências
|
|
54
|
+
- **⛔ PAUSA:** Aprovar / Repriorizar / Adicionar-remover tasks
|
|
55
|
+
|
|
56
|
+
### FASE 5: IMPLEMENT
|
|
57
|
+
1. Implementar task por task
|
|
58
|
+
2. `npx morph-spec task done {feature} {task-id}` após cada task
|
|
59
|
+
3. Framework gerencia checkpoints automaticamente (a cada 3 tasks)
|
|
60
|
+
4. Gerar recap.md ao final
|
|
61
|
+
|
|
62
|
+
### FASE 6: SYNC (condicional - se complexidade média/alta)
|
|
63
|
+
1. Revisar decisions.md, categorizar (coding, architecture, azure, integrations, ui-ux)
|
|
64
|
+
2. Promover para `.morph/project/standards/{category}.md`
|
|
65
|
+
3. Gerar commit dedicado de sync
|
|
66
|
+
- **⛔ PAUSA:** Aprovar promoção de decisões para standards
|
|
67
|
+
|
|
68
|
+
## Outputs Completos
|
|
69
|
+
proposal.md, ui-design-system.md, ui-mockups.md, ui-components.md, ui-flows.md, spec.md, contracts.cs, tasks.json, decisions.md, recap.md
|
|
70
|
+
|
|
71
|
+
## Exemplos
|
|
72
|
+
- "Sistema de relatórios com jobs agendados Hangfire"
|
|
73
|
+
- "Autenticação completa com Clerk (login, signup, OAuth)"
|
|
74
|
+
- "Dashboard com gráficos, tabelas e filtros complexos"
|
|
75
|
+
- "RAG pipeline com Azure AI Search e embeddings"
|
|
76
|
+
- "Infraestrutura Azure completa com Bicep"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Workflow: STANDARD (Média Complexidade)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** paginação, filtro, refatorar, performance, exportar
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- 3-10 arquivos, 50-500 linhas, 1-2 componentes simples
|
|
8
|
+
- Sem infraestrutura complexa, decisões táticas (não estratégicas)
|
|
9
|
+
|
|
10
|
+
## Fases
|
|
11
|
+
|
|
12
|
+
### 1. FASE 0: PROPOSAL (simplificada)
|
|
13
|
+
- Análise inicial em 1 parágrafo
|
|
14
|
+
- Detecta agentes relevantes
|
|
15
|
+
- **PAUSA:** Aprovar?
|
|
16
|
+
|
|
17
|
+
### 2. FASE 2: DESIGN (apenas spec.md)
|
|
18
|
+
- Spec técnico conciso (1-2 páginas)
|
|
19
|
+
- Sem contracts.cs se trivial
|
|
20
|
+
- Decisões táticas em decisions.md
|
|
21
|
+
- **PAUSA:** Aprovar?
|
|
22
|
+
|
|
23
|
+
### 3. FASE 4: TASKS (se > 5 tasks)
|
|
24
|
+
- Breakdown em tasks
|
|
25
|
+
- **PAUSA:** Aprovar?
|
|
26
|
+
|
|
27
|
+
### 4. FASE 5: IMPLEMENT
|
|
28
|
+
- Implementa task por task
|
|
29
|
+
- Gera recap.md ao final
|
|
30
|
+
|
|
31
|
+
## Outputs
|
|
32
|
+
proposal.md, spec.md, recap.md (mínimo necessário)
|
|
33
|
+
|
|
34
|
+
## Fases Puladas
|
|
35
|
+
- FASE 1 (SETUP) - contexto já carregado
|
|
36
|
+
- FASE 1.5 (UI/UX) - se não tiver front-end significativo
|
|
37
|
+
- FASE 3 (CLARIFY) - se spec for claro
|
|
38
|
+
- FASE 6 (SYNC) - decisões não são estratégicas
|
|
39
|
+
|
|
40
|
+
## Exemplos
|
|
41
|
+
- "Adicionar paginação na tabela de usuários"
|
|
42
|
+
- "Criar filtro por data no relatório"
|
|
43
|
+
- "Refatorar serviço de email para async"
|
|
44
|
+
- "Adicionar botão de exportar CSV"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Workflow: UI REFRESH (Redesign Visual)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** redesign, redesenhar, bonito, visual, estetica, modernizar
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- Páginas existentes com código funcional
|
|
8
|
+
- Apenas mudanças visuais (CSS, HTML, layout)
|
|
9
|
+
- Sem mudanças em lógica de negócio, sem infraestrutura
|
|
10
|
+
|
|
11
|
+
## Fases
|
|
12
|
+
|
|
13
|
+
### 1. ANÁLISE VISUAL (FASE 0+1 combinadas)
|
|
14
|
+
- Listar páginas a redesenhar
|
|
15
|
+
- Identificar componentes compartilhados e design system existente
|
|
16
|
+
- Se protótipo existir: ler e extrair padrões
|
|
17
|
+
- **PAUSA:** Escolher direção estética
|
|
18
|
+
|
|
19
|
+
### 2. DESIGN SYSTEM (FASE 1.5 simplificada)
|
|
20
|
+
- Definir variáveis CSS novas
|
|
21
|
+
- Listar componentes CSS a criar (checklist)
|
|
22
|
+
- Gerar/atualizar design-system.css
|
|
23
|
+
- **PAUSA:** Aprovar componentes
|
|
24
|
+
|
|
25
|
+
### 3. IMPLEMENT (por página)
|
|
26
|
+
- Atualizar CSS primeiro, depois cada página .razor
|
|
27
|
+
- Build incremental a cada 2-3 páginas
|
|
28
|
+
- Validar com `morph-spec validate-css`
|
|
29
|
+
|
|
30
|
+
## Outputs
|
|
31
|
+
design-refresh-checklist.md, CSS atualizado, páginas .razor, recap.md
|
|
32
|
+
|
|
33
|
+
## Fases Puladas
|
|
34
|
+
Setup completo, Contracts, Tasks detalhadas, Infra, Clarify, Sync
|
|
35
|
+
|
|
36
|
+
## Exemplos
|
|
37
|
+
- "Redesenhar as páginas do checkout para ficar mais bonito"
|
|
38
|
+
- "Modernizar visual do dashboard"
|
|
39
|
+
- "Aplicar novo design system nas telas existentes"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polymorphism-tech/morph-spec",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.4",
|
|
4
4
|
"description": "MORPH-SPEC: AI-First development framework with validation pipeline and multi-stack support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"files": [
|
|
27
27
|
"bin/",
|
|
28
28
|
"src/",
|
|
29
|
+
".morph/",
|
|
30
|
+
"framework/",
|
|
29
31
|
"scripts/",
|
|
30
|
-
"stacks/",
|
|
31
32
|
"docs/",
|
|
32
33
|
"README.md",
|
|
33
34
|
"LICENSE",
|
|
@@ -38,7 +39,6 @@
|
|
|
38
39
|
"node": ">=18.0.0"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
|
-
"postinstall": "node scripts/postinstall.js",
|
|
42
42
|
"start": "node bin/morph-spec.js",
|
|
43
43
|
"test": "node --test --test-concurrency=1",
|
|
44
44
|
"test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov node --test --test-concurrency=1",
|
|
@@ -11,22 +11,26 @@ import ora from 'ora';
|
|
|
11
11
|
import chalk from 'chalk';
|
|
12
12
|
import { logger } from '../../utils/logger.js';
|
|
13
13
|
import { ensureDir, writeFile } from '../../utils/file-copier.js';
|
|
14
|
-
import { resolveTemplatesDir } from '../../lib/stacks/stack-resolver.js';
|
|
15
14
|
|
|
16
15
|
// ============================================================================
|
|
17
16
|
// Helper Functions
|
|
18
17
|
// ============================================================================
|
|
19
18
|
|
|
19
|
+
function resolveTemplatesDir(basePath) {
|
|
20
|
+
return path.join(basePath, '.morph', 'templates');
|
|
21
|
+
}
|
|
22
|
+
|
|
20
23
|
function readTemplate(templateName) {
|
|
21
|
-
// Try npm-installed package path first
|
|
22
|
-
const
|
|
23
|
-
const templatePath = path.join(
|
|
24
|
+
// Try npm-installed package path first (framework templates)
|
|
25
|
+
const pkgFrameworkDir = path.join(process.cwd(), 'node_modules/@polymorphism-tech/morph-spec', 'framework', 'templates');
|
|
26
|
+
const templatePath = path.join(pkgFrameworkDir, templateName);
|
|
24
27
|
|
|
25
28
|
// Fallback to local if in development
|
|
26
29
|
if (!fs.existsSync(templatePath)) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// Check project-local override first, then framework
|
|
31
|
+
const localMorphPath = path.join(resolveTemplatesDir(process.cwd()), templateName);
|
|
32
|
+
if (fs.existsSync(localMorphPath)) {
|
|
33
|
+
return fs.readFileSync(localMorphPath, 'utf-8');
|
|
30
34
|
}
|
|
31
35
|
throw new Error(`Template not found: ${templateName}`);
|
|
32
36
|
}
|
|
@@ -6,14 +6,13 @@ import { logger } from '../../utils/logger.js';
|
|
|
6
6
|
import { analyzeRequestComplexity } from '../../lib/analysis/complexity-analyzer.js';
|
|
7
7
|
import { LearningSystem } from '../../lib/learning/learning-system.js';
|
|
8
8
|
import { loadStandardsForAgent, getStandardsListForAgent } from '../../lib/standards/standards-context-injector.js';
|
|
9
|
-
import { resolveAgentsConfigPath } from '../../lib/stacks/stack-resolver.js';
|
|
10
9
|
|
|
11
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
11
|
const frameworkRoot = join(__dirname, '..', '..', '..');
|
|
13
12
|
|
|
14
13
|
function loadAgentsConfig() {
|
|
15
14
|
try {
|
|
16
|
-
const configPath =
|
|
15
|
+
const configPath = join(frameworkRoot, '.morph/config/agents.json');
|
|
17
16
|
const content = readFileSync(configPath, 'utf8');
|
|
18
17
|
return JSON.parse(content);
|
|
19
18
|
} catch (err) {
|
|
@@ -21,6 +21,8 @@ import { saveProjectMorphVersion, getInstalledCLIVersion } from '../../utils/ver
|
|
|
21
21
|
import { installClaudeHooks } from '../../utils/hooks-installer.js';
|
|
22
22
|
import { AutoContextOrchestrator } from '../../core/orchestrator.js';
|
|
23
23
|
import { detectClaudeCode } from '../../llm/environment-detector.js';
|
|
24
|
+
import inquirer from 'inquirer';
|
|
25
|
+
import { detectProject } from '../../lib/detectors/index.js';
|
|
24
26
|
|
|
25
27
|
export async function initCommand(options) {
|
|
26
28
|
const targetPath = options.path || process.cwd();
|
|
@@ -77,7 +79,6 @@ export async function initCommand(options) {
|
|
|
77
79
|
frameworkVersion: getInstalledCLIVersion(),
|
|
78
80
|
project: {
|
|
79
81
|
name: dirName,
|
|
80
|
-
stack: 'unknown',
|
|
81
82
|
architecture: 'unknown'
|
|
82
83
|
}
|
|
83
84
|
};
|
|
@@ -107,21 +108,16 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
107
108
|
`;
|
|
108
109
|
await writeFile(contextReadme, readmeContent);
|
|
109
110
|
|
|
110
|
-
// 5. Copy templates from
|
|
111
|
-
spinner.text = 'Copying templates...';
|
|
111
|
+
// 5. Copy framework templates (project-local overrides start from framework defaults)
|
|
112
112
|
const contentDir = getContentDir();
|
|
113
|
-
const
|
|
113
|
+
const frameworkTemplatesSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'templates');
|
|
114
114
|
const templatesDest = join(morphPath, 'templates');
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const standardsSrc = join(contentDir, '.morph', 'standards');
|
|
122
|
-
const standardsDest = join(morphPath, 'standards');
|
|
123
|
-
if (await pathExists(standardsSrc)) {
|
|
124
|
-
await copyDirectory(standardsSrc, standardsDest);
|
|
115
|
+
let templatesCopied = false;
|
|
116
|
+
if (await pathExists(frameworkTemplatesSrc)) {
|
|
117
|
+
await copyDirectory(frameworkTemplatesSrc, templatesDest);
|
|
118
|
+
templatesCopied = true;
|
|
119
|
+
} else {
|
|
120
|
+
await ensureDir(templatesDest);
|
|
125
121
|
}
|
|
126
122
|
|
|
127
123
|
// 6b. Copy framework standards hierarchy (universal standards)
|
|
@@ -134,9 +130,9 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
134
130
|
logger.dim(' ✓ Copied framework standards: core/, backend/, frontend/, infrastructure/');
|
|
135
131
|
}
|
|
136
132
|
|
|
137
|
-
// 7. Copy agents.json
|
|
133
|
+
// 7. Copy agents.json (sourced from framework/ — canonical single source of truth)
|
|
138
134
|
spinner.text = 'Copying agents configuration...';
|
|
139
|
-
const agentsSrc = join(
|
|
135
|
+
const agentsSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'agents.json');
|
|
140
136
|
const agentsDest = join(configDir, 'agents.json');
|
|
141
137
|
if (await pathExists(agentsSrc)) {
|
|
142
138
|
await copyFile(agentsSrc, agentsDest);
|
|
@@ -156,24 +152,29 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
156
152
|
}
|
|
157
153
|
|
|
158
154
|
// 9. Copy .claude commands and create symlinks for skills
|
|
159
|
-
// Source: framework
|
|
155
|
+
// Source: framework/ (canonical for all stacks)
|
|
160
156
|
spinner.text = 'Setting up Claude Code integration...';
|
|
161
|
-
const
|
|
157
|
+
const frameworkDir = join(import.meta.dirname, '..', '..', '..', 'framework');
|
|
162
158
|
const claudeDest = join(targetPath, '.claude');
|
|
163
159
|
|
|
164
160
|
let symlinkCount = 0;
|
|
165
161
|
let copyCount = 0;
|
|
162
|
+
let commandsCopied = false;
|
|
163
|
+
|
|
164
|
+
// Copy commands directory (slash commands): framework/commands/ → .claude/commands/
|
|
165
|
+
const commandsSrc = join(frameworkDir, 'commands');
|
|
166
|
+
const commandsDest = join(claudeDest, 'commands');
|
|
167
|
+
if (await pathExists(commandsSrc)) {
|
|
168
|
+
await copyDirectory(commandsSrc, commandsDest);
|
|
169
|
+
commandsCopied = true;
|
|
170
|
+
} else {
|
|
171
|
+
logger.warn(' ⚠ framework/commands/ source missing — commands not installed');
|
|
172
|
+
}
|
|
166
173
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
if (await pathExists(commandsSrc)) {
|
|
172
|
-
await copyDirectory(commandsSrc, commandsDest);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Create directory links for skill categories (or copy if linking fails)
|
|
176
|
-
const skillsSrc = join(claudeSrc, 'skills');
|
|
174
|
+
// Create directory links for skill categories (or copy if linking fails)
|
|
175
|
+
// Source: framework/skills/ → .claude/skills/
|
|
176
|
+
{
|
|
177
|
+
const skillsSrc = join(frameworkDir, 'skills');
|
|
177
178
|
const skillsDest = join(claudeDest, 'skills');
|
|
178
179
|
|
|
179
180
|
if (await pathExists(skillsSrc)) {
|
|
@@ -254,9 +255,13 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
254
255
|
logger.dim(` ✓ CLAUDE.md`);
|
|
255
256
|
logger.dim(` ✓ .morph/config/ (config.json, agents.json, azure-pricing.json)`);
|
|
256
257
|
logger.dim(` ✓ .morph/standards/ (coding.md, architecture.md, azure.md, ...)`);
|
|
257
|
-
|
|
258
|
+
if (templatesCopied) {
|
|
259
|
+
logger.dim(` ✓ .morph/templates/ (project-local overrides for framework templates)`);
|
|
260
|
+
}
|
|
258
261
|
logger.dim(` ✓ .morph/project/ (context, standards, outputs)`);
|
|
259
|
-
|
|
262
|
+
if (commandsCopied) {
|
|
263
|
+
logger.dim(` ✓ .claude/commands/ (slash commands)`);
|
|
264
|
+
}
|
|
260
265
|
logger.dim(` ✓ .claude/settings.local.json (agent-teams hooks)`);
|
|
261
266
|
|
|
262
267
|
if (symlinkCount > 0) {
|
|
@@ -269,7 +274,49 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
269
274
|
|
|
270
275
|
logger.blank();
|
|
271
276
|
|
|
272
|
-
// 12.
|
|
277
|
+
// 12. Interactive stack/standards detection for existing projects
|
|
278
|
+
const hasProjectFiles = await pathExists(join(targetPath, 'package.json'))
|
|
279
|
+
|| await pathExists(join(targetPath, 'src'))
|
|
280
|
+
|| (await fs.readdir(targetPath)).some(f => f.endsWith('.csproj'));
|
|
281
|
+
|
|
282
|
+
if (hasProjectFiles) {
|
|
283
|
+
logger.blank();
|
|
284
|
+
logger.header('Existing Project Detected');
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
const quickResults = await detectProject(targetPath, { conversation: false, generateStandards: false });
|
|
288
|
+
const structure = quickResults.structure;
|
|
289
|
+
|
|
290
|
+
if (structure?.stack && structure.stack !== 'unknown') {
|
|
291
|
+
logger.info(`Stack detected: ${structure.stack}`);
|
|
292
|
+
if (structure?.architecture) logger.dim(`Architecture: ${structure.architecture}`);
|
|
293
|
+
if (structure?.uiLibrary) logger.dim(`UI Library: ${structure.uiLibrary}`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const { standardsChoice } = await inquirer.prompt([{
|
|
297
|
+
type: 'list',
|
|
298
|
+
name: 'standardsChoice',
|
|
299
|
+
message: 'How should morph-spec handle your project standards?',
|
|
300
|
+
choices: [
|
|
301
|
+
{ name: 'Keep morph-spec defaults (recommended)', value: 'morph-spec' },
|
|
302
|
+
{ name: 'Detect project-specific standards', value: 'detect' }
|
|
303
|
+
]
|
|
304
|
+
}]);
|
|
305
|
+
|
|
306
|
+
if (standardsChoice === 'detect') {
|
|
307
|
+
spinner.start('Generating project-specific standards...');
|
|
308
|
+
const fullResults = await detectProject(targetPath, { conversation: false });
|
|
309
|
+
const inferredPath = join(morphPath, 'project', 'standards', 'inferred.md');
|
|
310
|
+
await writeFile(inferredPath, fullResults.inferred.markdown);
|
|
311
|
+
spinner.succeed('Generated .morph/project/standards/inferred.md');
|
|
312
|
+
logger.dim('Review and edit .morph/project/standards/inferred.md as needed.');
|
|
313
|
+
}
|
|
314
|
+
} catch (error) {
|
|
315
|
+
logger.warn(`Stack detection failed: ${error.message}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// 13. LLM-based auto-detect project context (if Claude Code is available and not --skip-detection)
|
|
273
320
|
if (!options.skipDetection && detectClaudeCode()) {
|
|
274
321
|
logger.blank();
|
|
275
322
|
logger.header('Auto-Detecting Project Context');
|
|
@@ -99,7 +99,7 @@ export async function updateCommand(options) {
|
|
|
99
99
|
// Update templates
|
|
100
100
|
if (updateTemplates) {
|
|
101
101
|
updateSpinner.text = 'Updating templates...';
|
|
102
|
-
const templatesSrc = join(contentDir, '
|
|
102
|
+
const templatesSrc = join(contentDir, 'framework', 'templates');
|
|
103
103
|
const templatesDest = join(morphPath, 'templates');
|
|
104
104
|
await copyDirectory(templatesSrc, templatesDest);
|
|
105
105
|
}
|
|
@@ -107,14 +107,14 @@ export async function updateCommand(options) {
|
|
|
107
107
|
// Update standards
|
|
108
108
|
if (updateStandards) {
|
|
109
109
|
updateSpinner.text = 'Updating standards...';
|
|
110
|
-
const standardsSrc = join(contentDir, '
|
|
110
|
+
const standardsSrc = join(contentDir, 'framework', 'standards');
|
|
111
111
|
const standardsDest = join(morphPath, 'standards');
|
|
112
112
|
await copyDirectory(standardsSrc, standardsDest);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// Update agents.json
|
|
115
|
+
// Update agents.json (sourced from framework root .morph/config/ — canonical single source of truth)
|
|
116
116
|
updateSpinner.text = 'Updating agents configuration...';
|
|
117
|
-
const agentsSrc = join(
|
|
117
|
+
const agentsSrc = join(__dirname, '..', '..', '..', '.morph', 'config', 'agents.json');
|
|
118
118
|
const agentsDest = join(morphPath, 'config', 'agents.json');
|
|
119
119
|
if (await pathExists(agentsSrc)) {
|
|
120
120
|
await copyDirectory(agentsSrc, agentsDest);
|
|
@@ -125,12 +125,14 @@ export async function updateCommand(options) {
|
|
|
125
125
|
updateSpinner.text = 'Updating Claude commands and skills...';
|
|
126
126
|
const claudeSrc = join(__dirname, '..', '..', '..', '.claude');
|
|
127
127
|
const claudeDest = join(targetPath, '.claude');
|
|
128
|
+
let claudeUpdated = false;
|
|
128
129
|
if (await pathExists(claudeSrc)) {
|
|
129
130
|
// Copy commands (always copy, these are small)
|
|
130
131
|
const commandsSrc = join(claudeSrc, 'commands');
|
|
131
132
|
const commandsDest = join(claudeDest, 'commands');
|
|
132
133
|
if (await pathExists(commandsSrc)) {
|
|
133
134
|
await copyDirectory(commandsSrc, commandsDest);
|
|
135
|
+
claudeUpdated = true;
|
|
134
136
|
|
|
135
137
|
// Clean up stale command files moved to skills/workflows/ in v2.4+
|
|
136
138
|
const staleCommands = [
|
|
@@ -143,6 +145,8 @@ export async function updateCommand(options) {
|
|
|
143
145
|
await fs.remove(stalePath);
|
|
144
146
|
}
|
|
145
147
|
}
|
|
148
|
+
} else {
|
|
149
|
+
logger.warn(' ⚠ .claude/commands/ source missing — commands not updated');
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
// Update skills using directory links per category
|
|
@@ -200,7 +204,7 @@ export async function updateCommand(options) {
|
|
|
200
204
|
if (updateTemplates) logger.dim(' ✓ .morph/templates/');
|
|
201
205
|
if (updateStandards) logger.dim(' ✓ .morph/standards/');
|
|
202
206
|
logger.dim(' ✓ .morph/config/agents.json');
|
|
203
|
-
logger.dim(' ✓ .claude/commands/ and .claude/skills/');
|
|
207
|
+
if (claudeUpdated) logger.dim(' ✓ .claude/commands/ and .claude/skills/');
|
|
204
208
|
logger.dim(' ✓ .claude/settings.local.json (agent-teams hooks)');
|
|
205
209
|
logger.dim(' ✓ CLAUDE.md');
|
|
206
210
|
logger.blank();
|
|
@@ -25,14 +25,6 @@ export async function templateCustomizeCommand(templateId, options) {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
// 2. Check if template is framework (universal)
|
|
29
|
-
if (template.location !== 'framework') {
|
|
30
|
-
logger.warn(`Template "${templateId}" is already stack-specific`);
|
|
31
|
-
logger.dim(` Located at: stacks/${template.stacks?.[0]}/.morph/templates/${template.path}`);
|
|
32
|
-
logger.dim('\n You can edit it directly or copy to another stack.');
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
28
|
// 3. Resolve source path (framework template)
|
|
37
29
|
const projectPath = options.projectPath || process.cwd();
|
|
38
30
|
const sourcePath = resolveTemplatePathById(templateId, projectPath);
|
|
@@ -42,15 +34,9 @@ export async function templateCustomizeCommand(templateId, options) {
|
|
|
42
34
|
process.exit(1);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
// 4.
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
? join(projectPath, '.morph/templates', dirname(template.path))
|
|
49
|
-
: join(projectPath, 'stacks', stackId, '.morph/templates', dirname(template.path));
|
|
50
|
-
|
|
51
|
-
const destPath = options.local
|
|
52
|
-
? join(projectPath, '.morph/templates', template.path)
|
|
53
|
-
: join(projectPath, 'stacks', stackId, '.morph/templates', template.path);
|
|
37
|
+
// 4. Destination is always project-local .morph/templates/
|
|
38
|
+
const destDir = join(projectPath, '.morph/templates', dirname(template.path));
|
|
39
|
+
const destPath = join(projectPath, '.morph/templates', template.path);
|
|
54
40
|
|
|
55
41
|
// 5. Check if already exists
|
|
56
42
|
if (existsSync(destPath) && !options.force) {
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
getAllTemplates,
|
|
9
9
|
getTemplatesByCategory,
|
|
10
10
|
getTemplatesByPhase,
|
|
11
|
-
getTemplatesByStack,
|
|
12
11
|
getRequiredTemplates,
|
|
13
12
|
getRegistryStats
|
|
14
13
|
} from '../../core/templates/template-registry.js';
|
|
@@ -55,11 +54,8 @@ export async function templateListCommand(options) {
|
|
|
55
54
|
} else if (options.phase) {
|
|
56
55
|
templates = getTemplatesByPhase(options.phase);
|
|
57
56
|
logger.dim(`Phase: ${options.phase}`);
|
|
58
|
-
} else if (options.stack) {
|
|
59
|
-
templates = getTemplatesByStack(options.stack);
|
|
60
|
-
logger.dim(`Stack: ${options.stack}`);
|
|
61
57
|
} else if (options.required) {
|
|
62
|
-
templates = getRequiredTemplates(
|
|
58
|
+
templates = getRequiredTemplates();
|
|
63
59
|
logger.dim('Required templates only');
|
|
64
60
|
} else {
|
|
65
61
|
templates = getAllTemplates();
|
|
@@ -86,14 +82,6 @@ export async function templateListCommand(options) {
|
|
|
86
82
|
});
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
if (stackTemplates.length > 0) {
|
|
90
|
-
logger.info(chalk.bold.yellow(`\n📦 Stack-Specific Templates (${stackTemplates.length})`));
|
|
91
|
-
stackTemplates.forEach(t => {
|
|
92
|
-
const formatted = formatTemplate(t);
|
|
93
|
-
const stacks = t.stacks ? chalk.dim(`(${t.stacks.join(', ')})`) : '';
|
|
94
|
-
console.log(` ${formatted.id.padEnd(30)} ${formatted.name.padEnd(40)} ${stacks} ${formatted.badges}`);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
85
|
} else {
|
|
98
86
|
// Flat list
|
|
99
87
|
templates.forEach(t => {
|
|
@@ -109,8 +97,6 @@ export async function templateListCommand(options) {
|
|
|
109
97
|
logger.info(chalk.bold('\n📊 Statistics'));
|
|
110
98
|
console.log(` Total Templates: ${chalk.green(stats.total)}`);
|
|
111
99
|
console.log(` Framework: ${chalk.cyan(stats.framework)}`);
|
|
112
|
-
console.log(` Blazor-Azure: ${chalk.yellow(stats.blazorAzure)}`);
|
|
113
|
-
console.log(` Next.js-Supabase: ${chalk.yellow(stats.nextjsSupabase)}`);
|
|
114
100
|
console.log(` Required: ${chalk.green(stats.required)}`);
|
|
115
101
|
console.log(` Optional: ${chalk.dim(stats.optional)}`);
|
|
116
102
|
}
|
|
@@ -107,12 +107,11 @@ export async function templateRenderCommand(templateId, outputPath, variablesJso
|
|
|
107
107
|
|
|
108
108
|
// 2. Resolve template path
|
|
109
109
|
const projectPath = options.projectPath || process.cwd();
|
|
110
|
-
const
|
|
111
|
-
const templatePath = resolveTemplatePathById(templateId, projectPath, stackId);
|
|
110
|
+
const templatePath = resolveTemplatePathById(templateId, projectPath);
|
|
112
111
|
|
|
113
112
|
if (!templatePath) {
|
|
114
113
|
logger.error(`Template file not found for ${templateId}`);
|
|
115
|
-
logger.dim(' Searched in:
|
|
114
|
+
logger.dim(' Searched in: .morph/templates/ and framework/templates/');
|
|
116
115
|
process.exit(1);
|
|
117
116
|
}
|
|
118
117
|
|
|
@@ -76,15 +76,14 @@ export async function templateShowCommand(templateId, options) {
|
|
|
76
76
|
// Resolve actual path
|
|
77
77
|
if (options.showPath) {
|
|
78
78
|
const projectPath = options.projectPath || process.cwd();
|
|
79
|
-
const
|
|
80
|
-
const resolvedPath = resolveTemplatePathById(templateId, projectPath, stackId);
|
|
79
|
+
const resolvedPath = resolveTemplatePathById(templateId, projectPath);
|
|
81
80
|
|
|
82
81
|
logger.info(chalk.bold('📂 Resolved Path'));
|
|
83
82
|
if (resolvedPath) {
|
|
84
83
|
console.log(` ${chalk.green(resolvedPath)}`);
|
|
85
84
|
console.log(` ${chalk.dim(`(${existsSync(resolvedPath) ? 'exists' : 'not found'})`)}`);
|
|
86
85
|
} else {
|
|
87
|
-
console.log(` ${chalk.red('Not found in
|
|
86
|
+
console.log(` ${chalk.red('Not found in .morph/templates/ or framework/templates/')}`);
|
|
88
87
|
}
|
|
89
88
|
logger.blank();
|
|
90
89
|
}
|
|
@@ -92,8 +91,7 @@ export async function templateShowCommand(templateId, options) {
|
|
|
92
91
|
// Show template preview
|
|
93
92
|
if (options.preview) {
|
|
94
93
|
const projectPath = options.projectPath || process.cwd();
|
|
95
|
-
const
|
|
96
|
-
const resolvedPath = resolveTemplatePathById(templateId, projectPath, stackId);
|
|
94
|
+
const resolvedPath = resolveTemplatePathById(templateId, projectPath);
|
|
97
95
|
|
|
98
96
|
if (resolvedPath && existsSync(resolvedPath)) {
|
|
99
97
|
logger.info(chalk.bold('👁️ Preview (first 20 lines)'));
|
|
@@ -252,42 +252,28 @@ export function templateExists(templateId, projectPath = null) {
|
|
|
252
252
|
* Get template absolute path with fallback logic.
|
|
253
253
|
*
|
|
254
254
|
* Resolution order:
|
|
255
|
-
* 1.
|
|
255
|
+
* 1. Project-local override (.morph/templates/{path})
|
|
256
256
|
* 2. Framework universal template (framework/templates/{path})
|
|
257
257
|
*
|
|
258
258
|
* @param {string} templateId - Template identifier
|
|
259
259
|
* @param {string} projectPath - Project root path
|
|
260
|
-
* @param {string} [stackId] - Stack identifier (optional)
|
|
261
260
|
* @returns {string|null} Absolute template path or null if not found
|
|
262
261
|
*/
|
|
263
|
-
export function resolveTemplatePathById(templateId, projectPath
|
|
262
|
+
export function resolveTemplatePathById(templateId, projectPath) {
|
|
264
263
|
const template = getTemplateById(templateId, projectPath);
|
|
265
264
|
if (!template) {
|
|
266
265
|
return null;
|
|
267
266
|
}
|
|
268
267
|
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return
|
|
268
|
+
// 1. Project-local override
|
|
269
|
+
const projectLocalPath = join(projectPath, '.morph/templates', template.path);
|
|
270
|
+
if (existsSync(projectLocalPath)) {
|
|
271
|
+
return projectLocalPath;
|
|
273
272
|
}
|
|
274
273
|
|
|
275
|
-
//
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const stackPath = join(projectPath, 'stacks', stackId, '.morph/templates', template.path);
|
|
279
|
-
if (existsSync(stackPath)) {
|
|
280
|
-
return stackPath;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Fallback to framework if exists
|
|
284
|
-
const frameworkPath = join(projectPath, 'framework/templates', template.path);
|
|
285
|
-
if (existsSync(frameworkPath)) {
|
|
286
|
-
return frameworkPath;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return null;
|
|
274
|
+
// 2. Framework universal template
|
|
275
|
+
const frameworkPath = join(projectPath, 'framework/templates', template.path);
|
|
276
|
+
return existsSync(frameworkPath) ? frameworkPath : null;
|
|
291
277
|
}
|
|
292
278
|
|
|
293
279
|
/**
|