@polymorphism-tech/morph-spec 4.7.2 â 4.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.morph/analytics/threads-log.jsonl +54 -5
- package/.morph/state.json +152 -2
- package/LICENSE +1 -2
- package/README.md +379 -414
- package/bin/morph-spec.js +57 -394
- package/bin/validate.js +2 -26
- package/claude-plugin.json +2 -2
- package/docs/ARCHITECTURE.md +43 -46
- package/docs/CHEATSHEET.md +203 -221
- package/docs/COMMAND-FLOWS.md +319 -289
- package/docs/QUICKSTART.md +2 -8
- package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +2 -0
- package/docs/plans/2026-02-22-claude-settings.md +2 -0
- package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +2 -0
- package/docs/plans/2026-02-22-morph-spec-next.md +2 -0
- package/docs/plans/2026-02-22-native-alignment-design.md +2 -0
- package/docs/plans/2026-02-22-native-alignment-impl.md +2 -0
- package/docs/plans/2026-02-22-native-enrichment-design.md +2 -0
- package/docs/plans/2026-02-22-native-enrichment.md +2 -0
- package/docs/plans/2026-02-23-ddd-architecture-refactor.md +2 -0
- package/docs/plans/2026-02-23-ddd-nextsteps.md +2 -0
- package/docs/plans/2026-02-23-infra-architect-refactor.md +2 -0
- package/docs/plans/2026-02-23-nextjs-code-review-design.md +2 -1
- package/docs/plans/2026-02-23-nextjs-code-review-impl.md +2 -0
- package/docs/plans/2026-02-23-nextjs-standards-design.md +2 -1
- package/docs/plans/2026-02-23-nextjs-standards-impl.md +2 -0
- package/docs/plans/2026-02-24-cli-radical-simplification.md +592 -0
- package/docs/plans/2026-02-24-framework-failure-points.md +125 -0
- package/docs/plans/2026-02-24-morph-init-design.md +337 -0
- package/docs/plans/2026-02-24-morph-init-impl.md +1269 -0
- package/docs/plans/2026-02-24-tutorial-command-design.md +71 -0
- package/docs/plans/2026-02-24-tutorial-command.md +298 -0
- package/framework/CLAUDE.md +1 -1
- package/framework/commands/morph-proposal.md +3 -3
- package/framework/hooks/README.md +2 -5
- package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
- package/framework/hooks/claude-code/statusline.py +6 -1
- package/framework/hooks/dev/check-sync-health.js +117 -0
- package/framework/hooks/dev/guard-version-numbers.js +57 -0
- package/framework/hooks/dev/sync-standards-registry.js +60 -0
- package/framework/hooks/dev/sync-template-registry.js +60 -0
- package/framework/hooks/dev/validate-skill-format.js +70 -0
- package/framework/hooks/dev/validate-standard-format.js +73 -0
- package/framework/hooks/shared/payload-utils.js +39 -0
- package/framework/hooks/shared/state-reader.js +25 -1
- package/framework/rules/morph-workflow.md +1 -1
- package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
- package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
- package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
- package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
- package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
- package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
- package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
- package/framework/templates/examples/design-system-examples.md +1 -1
- package/framework/templates/ui/FluentDesignTheme.cs +1 -1
- package/framework/templates/ui/MudTheme.cs +1 -1
- package/framework/templates/ui/design-system.css +1 -1
- package/package.json +4 -2
- package/scripts/bump-version.js +248 -0
- package/scripts/install-dev-hooks.js +138 -0
- package/src/commands/agents/index.js +1 -2
- package/src/commands/index.js +13 -16
- package/src/commands/project/doctor.js +100 -14
- package/src/commands/project/index.js +7 -10
- package/src/commands/project/init.js +398 -528
- package/src/commands/project/install-plugin-cmd.js +28 -0
- package/src/commands/project/setup-infra-cmd.js +12 -0
- package/src/commands/project/tutorial.js +115 -0
- package/src/commands/state/approve.js +213 -221
- package/src/commands/state/index.js +0 -1
- package/src/commands/state/state.js +337 -365
- package/src/commands/templates/index.js +0 -4
- package/src/commands/trust/trust.js +1 -93
- package/src/commands/utils/index.js +1 -5
- package/src/commands/validation/index.js +1 -5
- package/src/core/registry/command-registry.js +11 -285
- package/src/core/state/state-manager.js +5 -2
- package/src/lib/detectors/index.js +81 -87
- package/src/lib/detectors/structure-detector.js +275 -273
- package/src/lib/generators/recap-generator.js +232 -225
- package/src/scripts/global-install.js +34 -0
- package/src/scripts/install-plugin.js +126 -0
- package/src/scripts/setup-infra.js +203 -0
- package/src/utils/agents-installer.js +10 -1
- package/src/utils/hooks-installer.js +66 -3
- package/.morph/.morphversion +0 -5
- package/.morph/config/config.json +0 -8
- package/.morph/framework/agents.json +0 -1815
- package/.morph/framework/hooks/README.md +0 -205
- package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +0 -54
- package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -83
- package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -42
- package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -61
- package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +0 -71
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -58
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +0 -64
- package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -94
- package/.morph/framework/hooks/claude-code/statusline.py +0 -538
- package/.morph/framework/hooks/claude-code/statusline.sh +0 -7
- package/.morph/framework/hooks/claude-code/stop/validate-completion.js +0 -88
- package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -91
- package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
- package/.morph/framework/hooks/git/pre-commit/agents.sh +0 -25
- package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
- package/.morph/framework/hooks/git/pre-commit/specs.sh +0 -50
- package/.morph/framework/hooks/git/pre-push/run-tests.sh +0 -44
- package/.morph/framework/hooks/shared/hook-response.js +0 -45
- package/.morph/framework/hooks/shared/phase-utils.js +0 -129
- package/.morph/framework/hooks/shared/state-reader.js +0 -138
- package/.morph/framework/hooks/shared/stdin-reader.js +0 -26
- package/.morph/framework/standards/STANDARDS.json +0 -933
- package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/.morph/framework/standards/ai-agents/production.md +0 -415
- package/.morph/framework/standards/ai-agents/setup.md +0 -418
- package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
- package/.morph/framework/standards/ai-agents/workflows.md +0 -354
- package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
- package/.morph/framework/standards/architecture/ddd/complexity-levels.md +0 -108
- package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
- package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
- package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
- package/.morph/framework/standards/backend/api/rest.md +0 -492
- package/.morph/framework/standards/backend/api/validation.md +0 -88
- package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
- package/.morph/framework/standards/backend/database/ef-core.md +0 -199
- package/.morph/framework/standards/backend/database/migrations.md +0 -393
- package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
- package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
- package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
- package/.morph/framework/standards/backend/dotnet/async.md +0 -366
- package/.morph/framework/standards/backend/dotnet/core.md +0 -117
- package/.morph/framework/standards/backend/dotnet/di.md +0 -439
- package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
- package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
- package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
- package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
- package/.morph/framework/standards/context/analytics.md +0 -96
- package/.morph/framework/standards/context/bundles.md +0 -110
- package/.morph/framework/standards/context/priming.md +0 -78
- package/.morph/framework/standards/core/architecture.md +0 -185
- package/.morph/framework/standards/core/coding.md +0 -214
- package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
- package/.morph/framework/standards/core/git.md +0 -185
- package/.morph/framework/standards/core/testing.md +0 -295
- package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
- package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
- package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
- package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
- package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/.morph/framework/standards/frontend/blazor/state.md +0 -191
- package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
- package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
- package/.morph/framework/standards/frontend/nextjs/app-router.md +0 -123
- package/.morph/framework/standards/frontend/nextjs/components.md +0 -132
- package/.morph/framework/standards/frontend/nextjs/data-fetching.md +0 -126
- package/.morph/framework/standards/frontend/nextjs/forms.md +0 -128
- package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +0 -67
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
- package/.morph/framework/standards/frontend/nextjs/project-structure.md +0 -102
- package/.morph/framework/standards/frontend/nextjs/state-management.md +0 -72
- package/.morph/framework/standards/frontend/nextjs/testing.md +0 -111
- package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
- package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
- package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
- package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
- package/.morph/framework/standards/integration/api/graphql.md +0 -91
- package/.morph/framework/standards/integration/api/grpc.md +0 -114
- package/.morph/framework/standards/integration/api/rest-design.md +0 -95
- package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
- package/.morph/framework/standards/observability/logging.md +0 -131
- package/.morph/framework/standards/observability/metrics.md +0 -121
- package/.morph/framework/standards/observability/monitoring.md +0 -114
- package/.morph/framework/standards/observability/tracing.md +0 -132
- package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
- package/.morph/framework/standards/workflows/thread-management.md +0 -113
- package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
- package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
- package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
- package/.morph/framework/templates/README.md +0 -814
- package/.morph/framework/templates/REGISTRY.json +0 -1888
- package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
- package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
- package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
- package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
- package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
- package/.morph/framework/templates/code/dotnet/test.cs +0 -239
- package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
- package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
- package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
- package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
- package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
- package/.morph/framework/templates/context/CONTEXT.md +0 -181
- package/.morph/framework/templates/docs/clarifications.md +0 -253
- package/.morph/framework/templates/docs/onboarding.md +0 -123
- package/.morph/framework/templates/docs/proposal.md +0 -182
- package/.morph/framework/templates/docs/schema-analysis.md +0 -119
- package/.morph/framework/templates/docs/spec.md +0 -198
- package/.morph/framework/templates/docs/ui-components.md +0 -124
- package/.morph/framework/templates/docs/ui-design-system.md +0 -76
- package/.morph/framework/templates/docs/ui-flows.md +0 -167
- package/.morph/framework/templates/docs/ui-mockups.md +0 -98
- package/.morph/framework/templates/docs/user-stories.md +0 -34
- package/.morph/framework/templates/examples/design-system-examples.md +0 -357
- package/.morph/framework/templates/examples/spec-examples.md +0 -90
- package/.morph/framework/templates/feature/decisions.md +0 -187
- package/.morph/framework/templates/feature/recap.md +0 -146
- package/.morph/framework/templates/feature/tasks.md +0 -199
- package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +0 -43
- package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +0 -26
- package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +0 -32
- package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +0 -56
- package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +0 -22
- package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +0 -26
- package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +0 -54
- package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
- package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
- package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
- package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
- package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
- package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
- package/.morph/framework/templates/infrastructure/github/README.md +0 -593
- package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
- package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
- package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
- package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
- package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
- package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
- package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
- package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
- package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
- package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
- package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
- package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
- package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
- package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
- package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
- package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
- package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
- package/.morph/framework/templates/project-structure/dotnet-ddd.md +0 -70
- package/.morph/framework/templates/saas/subscription.cs +0 -347
- package/.morph/framework/templates/saas/tenant.cs +0 -338
- package/.morph/framework/templates/state.template.json +0 -17
- package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/.morph/framework/templates/ui/MudTheme.cs +0 -281
- package/.morph/framework/templates/ui/design-system.css +0 -226
- package/.morph/logs/tool-failures.log +0 -17
- package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +0 -16
- package/.morph/plans/eager-watching-bunny.md +0 -105
- package/.morph/plans/temporal-seeking-nebula.md +0 -45
- package/CLAUDE.md +0 -77
- package/docs/claude-alignment-report.md +0 -137
- package/docs/examples/order-management/contracts.cs +0 -84
- package/docs/examples/order-management/proposal.md +0 -24
- package/docs/examples/order-management/spec.md +0 -162
- package/src/commands/feature/create-story.js +0 -362
- package/src/commands/feature/index.js +0 -6
- package/src/commands/feature/shard-spec.js +0 -225
- package/src/commands/feature/sprint-status.js +0 -250
- package/src/commands/generation/generate-onboarding.js +0 -169
- package/src/commands/generation/generate.js +0 -276
- package/src/commands/generation/index.js +0 -5
- package/src/commands/learning/capture-pattern.js +0 -121
- package/src/commands/learning/index.js +0 -5
- package/src/commands/learning/search-patterns.js +0 -126
- package/src/commands/mcp/mcp.js +0 -102
- package/src/commands/project/changes.js +0 -66
- package/src/commands/project/cost.js +0 -179
- package/src/commands/project/diff.js +0 -278
- package/src/commands/project/revert.js +0 -173
- package/src/commands/project/standards.js +0 -80
- package/src/commands/project/sync.js +0 -167
- package/src/commands/project/update-agents.js +0 -23
- package/src/commands/state/rollback-phase.js +0 -185
- package/src/commands/templates/template-customize.js +0 -87
- package/src/commands/templates/template-list.js +0 -114
- package/src/commands/templates/template-show.js +0 -129
- package/src/commands/templates/template-validate.js +0 -91
- package/src/commands/utils/troubleshoot.js +0 -222
- package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
- package/src/commands/validation/lint-fluent.js +0 -352
- package/src/commands/validation/validate-blazor-state.js +0 -210
- package/src/commands/validation/validate-blazor.js +0 -156
- package/src/commands/validation/validate-css.js +0 -84
- package/src/lib/detectors/conversation-analyzer.js +0 -163
- package/src/lib/learning/index.js +0 -7
- package/src/lib/learning/learning-system.js +0 -520
- package/src/lib/troubleshooting/index.js +0 -8
- package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
- package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
- package/src/llm/environment-detector.js +0 -43
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* update-agents command
|
|
3
|
-
*
|
|
4
|
-
* Refreshes .claude/agents/ with the latest tier-1 and tier-2 MORPH agents
|
|
5
|
-
* from the framework. Useful after upgrading morph-spec to pick up new or
|
|
6
|
-
* updated agent definitions without re-running full init.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { join, dirname } from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
import { installAgents } from '../../utils/agents-installer.js';
|
|
12
|
-
import { logger } from '../../utils/logger.js';
|
|
13
|
-
|
|
14
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
-
const FRAMEWORK_DIR = join(__dirname, '..', '..', '..', 'framework');
|
|
16
|
-
|
|
17
|
-
export async function updateAgentsCommand(args, options) {
|
|
18
|
-
const projectDir = process.cwd();
|
|
19
|
-
|
|
20
|
-
logger.info('Updating native subagents in .claude/agents/...');
|
|
21
|
-
await installAgents(projectDir, FRAMEWORK_DIR);
|
|
22
|
-
logger.success('Native subagents updated. Claude Code will discover them on next session start.');
|
|
23
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MORPH-SPEC Rollback Phase Command
|
|
3
|
-
*
|
|
4
|
-
* Rolls back a feature to a previous phase, marking outputs as draft.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* morph-spec rollback <feature-name> <target-phase>
|
|
8
|
-
*
|
|
9
|
-
* Example:
|
|
10
|
-
* morph-spec rollback scheduled-reports design
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import fs from 'fs';
|
|
14
|
-
import path from 'path';
|
|
15
|
-
import chalk from 'chalk';
|
|
16
|
-
import { loadState, saveState, getFeature, updateFeature } from '../../core/state/state-manager.js';
|
|
17
|
-
|
|
18
|
-
// Phase order
|
|
19
|
-
const PHASE_ORDER = ['proposal', 'setup', 'uiux', 'design', 'clarify', 'tasks', 'implement', 'sync'];
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Get phase index
|
|
23
|
-
*/
|
|
24
|
-
function getPhaseIndex(phase) {
|
|
25
|
-
return PHASE_ORDER.indexOf(phase);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get outputs that should be marked as draft when rolling back
|
|
30
|
-
*/
|
|
31
|
-
function getOutputsToReset(fromPhase, toPhase) {
|
|
32
|
-
const fromIndex = getPhaseIndex(fromPhase);
|
|
33
|
-
const toIndex = getPhaseIndex(toPhase);
|
|
34
|
-
|
|
35
|
-
// Map phases to their outputs
|
|
36
|
-
const phaseOutputs = {
|
|
37
|
-
'proposal': ['proposal'],
|
|
38
|
-
'setup': [],
|
|
39
|
-
'uiux': ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
|
|
40
|
-
'design': ['spec', 'contracts', 'decisions'],
|
|
41
|
-
'clarify': [],
|
|
42
|
-
'tasks': ['tasks'],
|
|
43
|
-
'implement': ['recap'],
|
|
44
|
-
'sync': []
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const outputsToReset = [];
|
|
48
|
-
|
|
49
|
-
// Collect all outputs from phases after target
|
|
50
|
-
for (let i = toIndex + 1; i <= fromIndex; i++) {
|
|
51
|
-
const phase = PHASE_ORDER[i];
|
|
52
|
-
if (phaseOutputs[phase]) {
|
|
53
|
-
outputsToReset.push(...phaseOutputs[phase]);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return outputsToReset;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Main command handler
|
|
62
|
-
*/
|
|
63
|
-
export async function rollbackPhaseCommand(feature, targetPhase, options = {}) {
|
|
64
|
-
console.log(chalk.cyan('\nââââââââââââââââââââââââââââââââââââââââââââââââââ'));
|
|
65
|
-
console.log(chalk.cyan('â MORPH-SPEC ROLLBACK â'));
|
|
66
|
-
console.log(chalk.cyan('ââââââââââââââââââââââââââââââââââââââââââââââââââ\n'));
|
|
67
|
-
|
|
68
|
-
// Validate target phase
|
|
69
|
-
if (!PHASE_ORDER.includes(targetPhase)) {
|
|
70
|
-
console.log(chalk.red(`â Invalid phase: ${targetPhase}`));
|
|
71
|
-
console.log(chalk.gray('\nValid phases:'));
|
|
72
|
-
PHASE_ORDER.forEach(p => console.log(chalk.gray(` - ${p}`)));
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Get current feature state
|
|
77
|
-
let featureState;
|
|
78
|
-
try {
|
|
79
|
-
featureState = getFeature(feature);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.log(chalk.red(`â Feature not found: ${feature}`));
|
|
82
|
-
console.log(chalk.gray(' Run: morph-spec state list'));
|
|
83
|
-
process.exit(1);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!featureState) {
|
|
87
|
-
console.log(chalk.red(`â Feature not found: ${feature}`));
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const currentPhase = featureState.phase || 'proposal';
|
|
92
|
-
const currentIndex = getPhaseIndex(currentPhase);
|
|
93
|
-
const targetIndex = getPhaseIndex(targetPhase);
|
|
94
|
-
|
|
95
|
-
// Check if rollback makes sense
|
|
96
|
-
if (targetIndex >= currentIndex) {
|
|
97
|
-
console.log(chalk.yellow(`â ī¸ Cannot rollback: target phase '${targetPhase}' is not before current phase '${currentPhase}'`));
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Get outputs to reset
|
|
102
|
-
const outputsToReset = getOutputsToReset(currentPhase, targetPhase);
|
|
103
|
-
|
|
104
|
-
// Show what will happen
|
|
105
|
-
console.log(chalk.gray('Feature:'), feature);
|
|
106
|
-
console.log(chalk.gray('Current Phase:'), currentPhase);
|
|
107
|
-
console.log(chalk.gray('Target Phase:'), targetPhase);
|
|
108
|
-
console.log('');
|
|
109
|
-
|
|
110
|
-
if (outputsToReset.length > 0) {
|
|
111
|
-
console.log(chalk.yellow('Outputs that will be marked as draft:'));
|
|
112
|
-
outputsToReset.forEach(o => {
|
|
113
|
-
console.log(chalk.gray(` - ${o}`));
|
|
114
|
-
});
|
|
115
|
-
console.log('');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Confirm unless --force
|
|
119
|
-
if (!options.force) {
|
|
120
|
-
console.log(chalk.yellow('â ī¸ This will:'));
|
|
121
|
-
console.log(chalk.gray(' 1. Set phase back to: ' + targetPhase));
|
|
122
|
-
console.log(chalk.gray(' 2. Reset task progress'));
|
|
123
|
-
console.log(chalk.gray(' 3. Mark outputs as not created (files remain on disk)'));
|
|
124
|
-
console.log('');
|
|
125
|
-
console.log(chalk.gray('Run with --force to confirm.'));
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Perform rollback
|
|
130
|
-
try {
|
|
131
|
-
const state = loadState();
|
|
132
|
-
|
|
133
|
-
// Update phase
|
|
134
|
-
state.features[feature].phase = targetPhase;
|
|
135
|
-
state.features[feature].status = 'in_progress';
|
|
136
|
-
state.features[feature].updatedAt = new Date().toISOString();
|
|
137
|
-
|
|
138
|
-
// Reset outputs
|
|
139
|
-
for (const output of outputsToReset) {
|
|
140
|
-
if (state.features[feature].outputs[output]) {
|
|
141
|
-
state.features[feature].outputs[output].created = false;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Reset tasks if rolling back before tasks phase
|
|
146
|
-
if (targetIndex < getPhaseIndex('tasks')) {
|
|
147
|
-
state.features[feature].tasks = {
|
|
148
|
-
total: 0,
|
|
149
|
-
completed: 0,
|
|
150
|
-
inProgress: 0,
|
|
151
|
-
pending: 0
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Add checkpoint for rollback
|
|
156
|
-
state.features[feature].checkpoints = state.features[feature].checkpoints || [];
|
|
157
|
-
state.features[feature].checkpoints.push({
|
|
158
|
-
timestamp: new Date().toISOString(),
|
|
159
|
-
phase: targetPhase,
|
|
160
|
-
completedTasks: 0,
|
|
161
|
-
note: `Rollback from ${currentPhase} to ${targetPhase}`
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// Track skipped phases (if any were skipped)
|
|
165
|
-
if (!state.features[feature].skippedPhases) {
|
|
166
|
-
state.features[feature].skippedPhases = [];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
saveState(state);
|
|
170
|
-
|
|
171
|
-
console.log(chalk.green('â
Rollback completed!'));
|
|
172
|
-
console.log('');
|
|
173
|
-
console.log(chalk.gray('Current state:'));
|
|
174
|
-
console.log(chalk.gray(` Phase: ${targetPhase}`));
|
|
175
|
-
console.log(chalk.gray(` Status: in_progress`));
|
|
176
|
-
console.log('');
|
|
177
|
-
console.log(chalk.cyan('Next steps:'));
|
|
178
|
-
console.log(chalk.gray(` 1. Review and update outputs for phase: ${targetPhase}`));
|
|
179
|
-
console.log(chalk.gray(` 2. Run: morph-spec session-summary ${feature}`));
|
|
180
|
-
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.log(chalk.red(`â Rollback failed: ${error.message}`));
|
|
183
|
-
process.exit(1);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template Customize Command - Copy a framework template to project for customization
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { copyFileSync, existsSync, mkdirSync } from 'fs';
|
|
6
|
-
import { join, dirname } from 'path';
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { logger } from '../../utils/logger.js';
|
|
9
|
-
import { getTemplateById, resolveTemplatePathById } from '../../core/templates/template-registry.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Customize template command - copies framework template to project .morph/framework/templates/
|
|
13
|
-
*/
|
|
14
|
-
export async function templateCustomizeCommand(templateId, options) {
|
|
15
|
-
logger.header(`Customizing Template: ${templateId}`);
|
|
16
|
-
logger.blank();
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
// 1. Validate template exists
|
|
20
|
-
const template = getTemplateById(templateId);
|
|
21
|
-
|
|
22
|
-
if (!template) {
|
|
23
|
-
logger.error(`Template not found: ${templateId}`);
|
|
24
|
-
logger.dim('\nđĄ Use `morph-spec template list` to see available templates');
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 3. Resolve source path (framework template)
|
|
29
|
-
const projectPath = options.projectPath || process.cwd();
|
|
30
|
-
const sourcePath = resolveTemplatePathById(templateId, projectPath);
|
|
31
|
-
|
|
32
|
-
if (!sourcePath) {
|
|
33
|
-
logger.error(`Framework template file not found for ${templateId}`);
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// 4. Destination is always project-local .morph/framework/templates/
|
|
38
|
-
const destDir = join(projectPath, '.morph/framework/templates', dirname(template.path));
|
|
39
|
-
const destPath = join(projectPath, '.morph/framework/templates', template.path);
|
|
40
|
-
|
|
41
|
-
// 5. Check if already exists
|
|
42
|
-
if (existsSync(destPath) && !options.force) {
|
|
43
|
-
logger.warn('Template already customized at this location');
|
|
44
|
-
logger.dim(` ${destPath}`);
|
|
45
|
-
logger.dim('\n Use --force to overwrite');
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// 6. Copy template
|
|
50
|
-
logger.dim(`Source: ${sourcePath}`);
|
|
51
|
-
logger.dim(`Destination: ${destPath}`);
|
|
52
|
-
logger.blank();
|
|
53
|
-
|
|
54
|
-
mkdirSync(destDir, { recursive: true });
|
|
55
|
-
copyFileSync(sourcePath, destPath);
|
|
56
|
-
|
|
57
|
-
logger.success('â
Template copied for customization');
|
|
58
|
-
logger.blank();
|
|
59
|
-
|
|
60
|
-
// 7. Show next steps
|
|
61
|
-
logger.info(chalk.bold('đ Next Steps'));
|
|
62
|
-
console.log(chalk.dim(' 1. Edit the template file:'));
|
|
63
|
-
console.log(chalk.cyan(` ${destPath}`));
|
|
64
|
-
console.log(chalk.dim('\n 2. Template will now be used instead of framework version'));
|
|
65
|
-
console.log(chalk.dim(' (Stack-specific templates take precedence)'));
|
|
66
|
-
console.log(chalk.dim('\n 3. Test rendering:'));
|
|
67
|
-
console.log(chalk.cyan(` morph-spec template render ${templateId} output.md '{"FEATURE_NAME":"test"}'`));
|
|
68
|
-
|
|
69
|
-
if (!options.local) {
|
|
70
|
-
console.log(chalk.dim('\n 4. To share across stacks, use --local flag'));
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
logger.blank();
|
|
74
|
-
|
|
75
|
-
// 8. Show warning about updates
|
|
76
|
-
logger.warn('â ī¸ Customized templates won\'t receive framework updates');
|
|
77
|
-
logger.dim(' To get updates: delete customized version and re-run this command');
|
|
78
|
-
logger.blank();
|
|
79
|
-
|
|
80
|
-
} catch (error) {
|
|
81
|
-
logger.error(`Failed to customize template: ${error.message}`);
|
|
82
|
-
if (options.verbose) {
|
|
83
|
-
console.error(error.stack);
|
|
84
|
-
}
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template List Command - List all available templates with filtering
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { logger } from '../../utils/logger.js';
|
|
7
|
-
import {
|
|
8
|
-
getAllTemplates,
|
|
9
|
-
getTemplatesByCategory,
|
|
10
|
-
getTemplatesByPhase,
|
|
11
|
-
getRequiredTemplates,
|
|
12
|
-
getRegistryStats
|
|
13
|
-
} from '../../core/templates/template-registry.js';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Format template for display
|
|
17
|
-
*/
|
|
18
|
-
function formatTemplate(template) {
|
|
19
|
-
const { id, name, category, phase, required, stackSpecific, location, engine, deprecated } = template;
|
|
20
|
-
|
|
21
|
-
const badges = [];
|
|
22
|
-
if (required) badges.push(chalk.green('[REQUIRED]'));
|
|
23
|
-
if (deprecated) badges.push(chalk.red('[DEPRECATED]'));
|
|
24
|
-
if (stackSpecific) badges.push(chalk.yellow('[STACK-SPECIFIC]'));
|
|
25
|
-
else badges.push(chalk.cyan('[UNIVERSAL]'));
|
|
26
|
-
if (engine === 'handlebars') badges.push(chalk.blue('[HBS]'));
|
|
27
|
-
|
|
28
|
-
const badgeStr = badges.join(' ');
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
id: chalk.bold(id),
|
|
32
|
-
name,
|
|
33
|
-
location: location === 'framework' ? chalk.cyan('framework') : chalk.yellow('stack'),
|
|
34
|
-
category: chalk.dim(category),
|
|
35
|
-
phase: chalk.dim(phase || 'N/A'),
|
|
36
|
-
badges: badgeStr
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* List templates command
|
|
42
|
-
*/
|
|
43
|
-
export async function templateListCommand(options) {
|
|
44
|
-
logger.header('MORPH-SPEC Templates');
|
|
45
|
-
logger.blank();
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
let templates;
|
|
49
|
-
|
|
50
|
-
// Apply filters
|
|
51
|
-
if (options.category) {
|
|
52
|
-
templates = getTemplatesByCategory(options.category);
|
|
53
|
-
logger.dim(`Category: ${options.category}`);
|
|
54
|
-
} else if (options.phase) {
|
|
55
|
-
templates = getTemplatesByPhase(options.phase);
|
|
56
|
-
logger.dim(`Phase: ${options.phase}`);
|
|
57
|
-
} else if (options.required) {
|
|
58
|
-
templates = getRequiredTemplates();
|
|
59
|
-
logger.dim('Required templates only');
|
|
60
|
-
} else {
|
|
61
|
-
templates = getAllTemplates();
|
|
62
|
-
logger.dim('All templates');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
logger.blank();
|
|
66
|
-
|
|
67
|
-
if (templates.length === 0) {
|
|
68
|
-
logger.warn('No templates found matching criteria');
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Group by location if not filtered
|
|
73
|
-
if (!options.category && !options.phase) {
|
|
74
|
-
const frameworkTemplates = templates.filter(t => t.location === 'framework');
|
|
75
|
-
const stackTemplates = templates.filter(t => t.location === 'stack');
|
|
76
|
-
|
|
77
|
-
if (frameworkTemplates.length > 0) {
|
|
78
|
-
logger.info(chalk.bold.cyan(`\nđĻ Universal Templates (${frameworkTemplates.length})`));
|
|
79
|
-
frameworkTemplates.forEach(t => {
|
|
80
|
-
const formatted = formatTemplate(t);
|
|
81
|
-
console.log(` ${formatted.id.padEnd(30)} ${formatted.name.padEnd(40)} ${formatted.badges}`);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
} else {
|
|
86
|
-
// Flat list
|
|
87
|
-
templates.forEach(t => {
|
|
88
|
-
const formatted = formatTemplate(t);
|
|
89
|
-
console.log(` ${formatted.id.padEnd(30)} ${formatted.name.padEnd(40)} ${formatted.location.padEnd(15)} ${formatted.badges}`);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Show statistics
|
|
94
|
-
if (!options.category && !options.phase && !options.stack && !options.required) {
|
|
95
|
-
logger.blank();
|
|
96
|
-
const stats = getRegistryStats();
|
|
97
|
-
logger.info(chalk.bold('\nđ Statistics'));
|
|
98
|
-
console.log(` Total Templates: ${chalk.green(stats.total)}`);
|
|
99
|
-
console.log(` Framework: ${chalk.cyan(stats.framework)}`);
|
|
100
|
-
console.log(` Required: ${chalk.green(stats.required)}`);
|
|
101
|
-
console.log(` Optional: ${chalk.dim(stats.optional)}`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
logger.blank();
|
|
105
|
-
|
|
106
|
-
// Show usage hint
|
|
107
|
-
logger.dim('đĄ Use `morph-spec template show <id>` to see template details');
|
|
108
|
-
logger.blank();
|
|
109
|
-
|
|
110
|
-
} catch (error) {
|
|
111
|
-
logger.error(`Failed to list templates: ${error.message}`);
|
|
112
|
-
process.exit(1);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template Show Command - Display detailed information about a template
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { logger } from '../../utils/logger.js';
|
|
7
|
-
import { getTemplateById, resolveTemplatePathById } from '../../core/templates/template-registry.js';
|
|
8
|
-
import { readFileSync, existsSync } from 'fs';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Show template details command
|
|
12
|
-
*/
|
|
13
|
-
export async function templateShowCommand(templateId, options) {
|
|
14
|
-
logger.header(`Template: ${templateId}`);
|
|
15
|
-
logger.blank();
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const template = getTemplateById(templateId);
|
|
19
|
-
|
|
20
|
-
if (!template) {
|
|
21
|
-
logger.error(`Template not found: ${templateId}`);
|
|
22
|
-
logger.dim('\nđĄ Use `morph-spec template list` to see available templates');
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Display template metadata
|
|
27
|
-
logger.info(chalk.bold('đ Metadata'));
|
|
28
|
-
console.log(` ID: ${chalk.cyan(template.id)}`);
|
|
29
|
-
console.log(` Name: ${chalk.green(template.name)}`);
|
|
30
|
-
console.log(` Path: ${chalk.dim(template.path)}`);
|
|
31
|
-
console.log(` Location: ${template.location === 'framework' ? chalk.cyan('framework') : chalk.yellow('stack')}`);
|
|
32
|
-
console.log(` Category: ${template.category}`);
|
|
33
|
-
console.log(` Phase: ${template.phase || 'N/A'}`);
|
|
34
|
-
console.log(` Required: ${template.required ? chalk.green('Yes') : chalk.dim('No')}`);
|
|
35
|
-
console.log(` Stack-Specific: ${template.stackSpecific ? chalk.yellow('Yes') : chalk.cyan('No (universal)')}`);
|
|
36
|
-
|
|
37
|
-
if (template.stackSpecific && template.stacks) {
|
|
38
|
-
console.log(` Stacks: ${chalk.yellow(template.stacks.join(', '))}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
console.log(` Engine: ${template.engine === 'handlebars' ? chalk.blue('Handlebars') : chalk.dim('Custom')}`);
|
|
42
|
-
|
|
43
|
-
if (template.deprecated) {
|
|
44
|
-
console.log(` ${chalk.red.bold('â ī¸ DEPRECATED')}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (template.autoGenerated) {
|
|
48
|
-
console.log(` ${chalk.dim('Auto-generated (not user-facing)')}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
logger.blank();
|
|
52
|
-
|
|
53
|
-
// Description
|
|
54
|
-
if (template.description) {
|
|
55
|
-
logger.info(chalk.bold('đ Description'));
|
|
56
|
-
console.log(` ${template.description}`);
|
|
57
|
-
logger.blank();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Placeholders
|
|
61
|
-
if (template.placeholders && template.placeholders.length > 0) {
|
|
62
|
-
logger.info(chalk.bold('đ Variables'));
|
|
63
|
-
template.placeholders.forEach(p => {
|
|
64
|
-
console.log(` ${chalk.cyan(`{{${p}}}`)}`);
|
|
65
|
-
});
|
|
66
|
-
logger.blank();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Output name
|
|
70
|
-
if (template.outputName) {
|
|
71
|
-
logger.info(chalk.bold('đ Output Name'));
|
|
72
|
-
console.log(` ${chalk.dim(template.outputName)}`);
|
|
73
|
-
logger.blank();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Resolve actual path
|
|
77
|
-
if (options.showPath) {
|
|
78
|
-
const projectPath = options.projectPath || process.cwd();
|
|
79
|
-
const resolvedPath = resolveTemplatePathById(templateId, projectPath);
|
|
80
|
-
|
|
81
|
-
logger.info(chalk.bold('đ Resolved Path'));
|
|
82
|
-
if (resolvedPath) {
|
|
83
|
-
console.log(` ${chalk.green(resolvedPath)}`);
|
|
84
|
-
console.log(` ${chalk.dim(`(${existsSync(resolvedPath) ? 'exists' : 'not found'})`)}`);
|
|
85
|
-
} else {
|
|
86
|
-
console.log(` ${chalk.red('Not found in .morph/framework/templates/ or framework/templates/')}`);
|
|
87
|
-
}
|
|
88
|
-
logger.blank();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Show template preview
|
|
92
|
-
if (options.preview) {
|
|
93
|
-
const projectPath = options.projectPath || process.cwd();
|
|
94
|
-
const resolvedPath = resolveTemplatePathById(templateId, projectPath);
|
|
95
|
-
|
|
96
|
-
if (resolvedPath && existsSync(resolvedPath)) {
|
|
97
|
-
logger.info(chalk.bold('đī¸ Preview (first 20 lines)'));
|
|
98
|
-
logger.blank();
|
|
99
|
-
|
|
100
|
-
const content = readFileSync(resolvedPath, 'utf-8');
|
|
101
|
-
const lines = content.split('\n').slice(0, 20);
|
|
102
|
-
|
|
103
|
-
lines.forEach((line, i) => {
|
|
104
|
-
console.log(chalk.dim(`${String(i + 1).padStart(3)} ${line}`));
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
if (content.split('\n').length > 20) {
|
|
108
|
-
logger.blank();
|
|
109
|
-
logger.dim(` ... (${content.split('\n').length - 20} more lines)`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
logger.blank();
|
|
113
|
-
} else {
|
|
114
|
-
logger.warn('Template file not found - cannot preview');
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Show usage hint
|
|
119
|
-
if (template.engine === 'handlebars') {
|
|
120
|
-
logger.info(chalk.bold('đĄ Usage Hint'));
|
|
121
|
-
console.log(chalk.dim(` morph-spec template render ${templateId} output.md '{"FEATURE_NAME":"my-feature"}'`));
|
|
122
|
-
logger.blank();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
} catch (error) {
|
|
126
|
-
logger.error(`Failed to show template: ${error.message}`);
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template Validate Command - Validate Handlebars templates
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { logger } from '../../utils/logger.js';
|
|
7
|
-
import { validateTemplate, validateAllTemplates, formatValidationResults, summarizeValidation } from '../../core/templates/template-validator.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Validate template(s) command
|
|
11
|
-
*/
|
|
12
|
-
export async function templateValidateCommand(templateId, options) {
|
|
13
|
-
const projectPath = options.projectPath || process.cwd();
|
|
14
|
-
|
|
15
|
-
if (templateId) {
|
|
16
|
-
// Validate single template
|
|
17
|
-
logger.header(`Validating Template: ${templateId}`);
|
|
18
|
-
logger.blank();
|
|
19
|
-
|
|
20
|
-
const result = validateTemplate(templateId, projectPath);
|
|
21
|
-
|
|
22
|
-
// Display results
|
|
23
|
-
if (result.errors.length === 0 && result.warnings.length === 0) {
|
|
24
|
-
logger.success(`â
Template is valid`);
|
|
25
|
-
logger.blank();
|
|
26
|
-
|
|
27
|
-
if (result.info.length > 0 && options.verbose) {
|
|
28
|
-
logger.info(chalk.bold('âšī¸ Information'));
|
|
29
|
-
result.info.forEach(info => console.log(chalk.dim(` ${info}`)));
|
|
30
|
-
logger.blank();
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
if (result.errors.length > 0) {
|
|
34
|
-
logger.error(chalk.bold('â Errors'));
|
|
35
|
-
result.errors.forEach(error => console.log(chalk.red(` - ${error}`)));
|
|
36
|
-
logger.blank();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (result.warnings.length > 0) {
|
|
40
|
-
logger.warn(chalk.bold('â ī¸ Warnings'));
|
|
41
|
-
result.warnings.forEach(warning => console.log(chalk.yellow(` - ${warning}`)));
|
|
42
|
-
logger.blank();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (result.info.length > 0 && options.verbose) {
|
|
46
|
-
logger.info(chalk.bold('âšī¸ Information'));
|
|
47
|
-
result.info.forEach(info => console.log(chalk.dim(` ${info}`)));
|
|
48
|
-
logger.blank();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (result.errors.length > 0) {
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
// Validate all templates
|
|
57
|
-
logger.header('Validating All Templates');
|
|
58
|
-
logger.blank();
|
|
59
|
-
|
|
60
|
-
const validationOptions = {
|
|
61
|
-
skipDeprecated: !options.includeDeprecated,
|
|
62
|
-
category: options.category,
|
|
63
|
-
technology: options.technology,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const results = validateAllTemplates(projectPath, validationOptions);
|
|
67
|
-
const summary = summarizeValidation(results);
|
|
68
|
-
|
|
69
|
-
// Display results
|
|
70
|
-
const formatted = formatValidationResults(results, {
|
|
71
|
-
showInfo: options.verbose,
|
|
72
|
-
showValid: options.showValid,
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
console.log(formatted);
|
|
76
|
-
logger.blank();
|
|
77
|
-
|
|
78
|
-
// Exit with error if any templates have errors
|
|
79
|
-
if (summary.hasErrors > 0) {
|
|
80
|
-
logger.error(`${summary.hasErrors} template(s) failed validation`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
} else if (summary.hasWarnings > 0) {
|
|
83
|
-
logger.warn(`${summary.hasWarnings} template(s) have warnings`);
|
|
84
|
-
if (options.strict) {
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
logger.success(`All templates are valid! â
`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|