@polymorphism-tech/morph-spec 4.7.2 ā 4.8.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/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/CHEATSHEET.md +203 -221
- package/docs/QUICKSTART.md +2 -8
- 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 +7 -5
- 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/analytics/threads-log.jsonl +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/.morph/state.json +0 -48
- package/CLAUDE.md +0 -77
- package/docs/ARCHITECTURE.md +0 -331
- package/docs/COMMAND-FLOWS.md +0 -368
- 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/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +0 -512
- package/docs/plans/2026-02-22-claude-settings.md +0 -515
- package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +0 -728
- package/docs/plans/2026-02-22-morph-spec-next.md +0 -478
- package/docs/plans/2026-02-22-native-alignment-design.md +0 -199
- package/docs/plans/2026-02-22-native-alignment-impl.md +0 -925
- package/docs/plans/2026-02-22-native-enrichment-design.md +0 -244
- package/docs/plans/2026-02-22-native-enrichment.md +0 -735
- package/docs/plans/2026-02-23-ddd-architecture-refactor.md +0 -1153
- package/docs/plans/2026-02-23-ddd-nextsteps.md +0 -682
- package/docs/plans/2026-02-23-infra-architect-refactor.md +0 -437
- package/docs/plans/2026-02-23-nextjs-code-review-design.md +0 -156
- package/docs/plans/2026-02-23-nextjs-code-review-impl.md +0 -1254
- package/docs/plans/2026-02-23-nextjs-standards-design.md +0 -149
- package/docs/plans/2026-02-23-nextjs-standards-impl.md +0 -1846
- package/scripts/generate-refs.js +0 -336
- package/scripts/generate-standards-registry.js +0 -44
- package/scripts/scan-nextjs.mjs +0 -169
- package/scripts/validate-real.mjs +0 -255
- 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,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Standards CLI Commands
|
|
3
|
-
*
|
|
4
|
-
* Provides browsable access to the framework standards registry.
|
|
5
|
-
* Usage:
|
|
6
|
-
* morph-spec standards --list
|
|
7
|
-
* morph-spec standards --search <query>
|
|
8
|
-
* morph-spec standards --show <id>
|
|
9
|
-
* morph-spec standards --category <cat>
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { readFileSync } from 'fs';
|
|
13
|
-
import { join } from 'path';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
|
-
import { logger } from '../../utils/logger.js';
|
|
16
|
-
|
|
17
|
-
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
18
|
-
const REGISTRY_PATH = join(__dirname, '..', '..', '..', 'framework', 'standards', 'STANDARDS.json');
|
|
19
|
-
|
|
20
|
-
function loadRegistry() {
|
|
21
|
-
return JSON.parse(readFileSync(REGISTRY_PATH, 'utf8')).standards;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* List all standards, optionally filtered by category.
|
|
26
|
-
* @param {{ json?: boolean, category?: string }} opts
|
|
27
|
-
* @returns {Promise<Array>}
|
|
28
|
-
*/
|
|
29
|
-
export async function listStandards({ json, category } = {}) {
|
|
30
|
-
let standards = loadRegistry();
|
|
31
|
-
if (category) {
|
|
32
|
-
standards = standards.filter(s => s.category === category);
|
|
33
|
-
}
|
|
34
|
-
if (json) return standards;
|
|
35
|
-
standards.forEach(s =>
|
|
36
|
-
logger.info(`${s.id.padEnd(55)} ${s.category}`)
|
|
37
|
-
);
|
|
38
|
-
return standards;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Search standards by query string (matches id, name, or tags).
|
|
43
|
-
* @param {string} query
|
|
44
|
-
* @param {{ json?: boolean }} opts
|
|
45
|
-
* @returns {Promise<Array>}
|
|
46
|
-
*/
|
|
47
|
-
export async function searchStandards(query, { json } = {}) {
|
|
48
|
-
const q = query.toLowerCase();
|
|
49
|
-
const results = loadRegistry().filter(s =>
|
|
50
|
-
s.name.toLowerCase().includes(q) ||
|
|
51
|
-
s.id.toLowerCase().includes(q) ||
|
|
52
|
-
s.tags.some(t => t.toLowerCase().includes(q))
|
|
53
|
-
);
|
|
54
|
-
if (json) return results;
|
|
55
|
-
if (results.length === 0) {
|
|
56
|
-
logger.warn(`No standards found matching "${query}"`);
|
|
57
|
-
} else {
|
|
58
|
-
results.forEach(s => logger.info(`${s.id}: ${s.name} [${s.category}]`));
|
|
59
|
-
}
|
|
60
|
-
return results;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Show the full content of a standard by its id.
|
|
65
|
-
* @param {string} id
|
|
66
|
-
* @returns {Promise<string|null>}
|
|
67
|
-
*/
|
|
68
|
-
export async function showStandard(id) {
|
|
69
|
-
const standard = loadRegistry().find(s => s.id === id);
|
|
70
|
-
if (!standard) {
|
|
71
|
-
logger.error(`Standard '${id}' not found. Use --list to see available standards.`);
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
const content = readFileSync(
|
|
75
|
-
join(__dirname, '..', '..', '..', 'framework', 'standards', standard.path),
|
|
76
|
-
'utf8'
|
|
77
|
-
);
|
|
78
|
-
logger.info(content);
|
|
79
|
-
return content;
|
|
80
|
-
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { readdirSync, existsSync } from 'fs';
|
|
3
|
-
import ora from 'ora';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import { logger } from '../../utils/logger.js';
|
|
6
|
-
import { readFile, writeFile, ensureDir } from '../../utils/file-copier.js';
|
|
7
|
-
import { analyzeConversation } from '../../lib/detectors/conversation-analyzer.js';
|
|
8
|
-
|
|
9
|
-
export async function syncCommand(options) {
|
|
10
|
-
const targetPath = options.path || process.cwd();
|
|
11
|
-
|
|
12
|
-
logger.header('MORPH-SPEC Standards Sync');
|
|
13
|
-
logger.dim(`Project: ${targetPath}`);
|
|
14
|
-
logger.blank();
|
|
15
|
-
|
|
16
|
-
const spinner = ora('Analyzing feature decisions...').start();
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
// 1. Find all decisions.md files
|
|
20
|
-
const outputsPath = join(targetPath, '.morph', 'project', 'outputs');
|
|
21
|
-
|
|
22
|
-
if (!existsSync(outputsPath)) {
|
|
23
|
-
spinner.warn('No features found');
|
|
24
|
-
logger.dim('Create features first using MORPH workflow.');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const features = readdirSync(outputsPath, { withFileTypes: true })
|
|
29
|
-
.filter(dirent => dirent.isDirectory())
|
|
30
|
-
.map(dirent => dirent.name);
|
|
31
|
-
|
|
32
|
-
if (features.length === 0) {
|
|
33
|
-
spinner.warn('No features found');
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
spinner.text = `Found ${features.length} features, analyzing decisions...`;
|
|
38
|
-
|
|
39
|
-
// 2. Analyze all decisions
|
|
40
|
-
const conversation = await analyzeConversation(targetPath);
|
|
41
|
-
|
|
42
|
-
if (conversation.decisions.length === 0) {
|
|
43
|
-
spinner.warn('No decisions found to sync');
|
|
44
|
-
logger.dim('Features may not have decisions.md files yet.');
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
spinner.succeed(`Found ${conversation.decisions.length} decisions`);
|
|
49
|
-
logger.blank();
|
|
50
|
-
|
|
51
|
-
// 3. Group by category
|
|
52
|
-
const byCategory = groupByCategory(conversation.decisions);
|
|
53
|
-
|
|
54
|
-
// 4. Display candidates
|
|
55
|
-
logger.header('Decisions by Category:');
|
|
56
|
-
logger.blank();
|
|
57
|
-
|
|
58
|
-
let totalCandidates = 0;
|
|
59
|
-
|
|
60
|
-
for (const [category, decisions] of Object.entries(byCategory)) {
|
|
61
|
-
if (decisions.length > 0) {
|
|
62
|
-
logger.info(chalk.cyan(`${formatCategory(category)} (${decisions.length})`));
|
|
63
|
-
decisions.slice(0, 3).forEach(d => {
|
|
64
|
-
const preview = d.text.split('\n')[0].substring(0, 70);
|
|
65
|
-
logger.dim(` - ${preview}...`);
|
|
66
|
-
});
|
|
67
|
-
if (decisions.length > 3) {
|
|
68
|
-
logger.dim(` ... and ${decisions.length - 3} more`);
|
|
69
|
-
}
|
|
70
|
-
logger.blank();
|
|
71
|
-
totalCandidates += decisions.length;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// 5. Sync (for now, just report - interactive approval would be added later)
|
|
76
|
-
if (options.dryRun) {
|
|
77
|
-
logger.warn('Dry run mode - no files updated');
|
|
78
|
-
logger.dim(`Would update ${Object.keys(byCategory).length} standard files`);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
spinner.start('Updating standards...');
|
|
83
|
-
|
|
84
|
-
const standardsDir = join(targetPath, '.morph', 'project', 'standards');
|
|
85
|
-
await ensureDir(standardsDir);
|
|
86
|
-
|
|
87
|
-
let updatedFiles = [];
|
|
88
|
-
|
|
89
|
-
for (const [category, decisions] of Object.entries(byCategory)) {
|
|
90
|
-
if (decisions.length === 0) continue;
|
|
91
|
-
|
|
92
|
-
const fileName = `${category}.md`;
|
|
93
|
-
const filePath = join(standardsDir, fileName);
|
|
94
|
-
|
|
95
|
-
// Read existing or create new
|
|
96
|
-
let content = '';
|
|
97
|
-
if (existsSync(filePath)) {
|
|
98
|
-
content = await readFile(filePath);
|
|
99
|
-
} else {
|
|
100
|
-
content = `# ${formatCategory(category)} Standards\n\n> Project-specific standards for ${category}\n\n`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Append new decisions
|
|
104
|
-
content += `\n## Decisions from Features (${new Date().toISOString().split('T')[0]})\n\n`;
|
|
105
|
-
|
|
106
|
-
decisions.forEach((d, idx) => {
|
|
107
|
-
const preview = d.text.split('\n').slice(0, 5).join('\n');
|
|
108
|
-
content += `### Decision ${idx + 1}\n\n${preview}\n\n`;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
await writeFile(filePath, content);
|
|
112
|
-
updatedFiles.push(fileName);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
spinner.succeed(`Updated ${updatedFiles.length} standard files`);
|
|
116
|
-
|
|
117
|
-
updatedFiles.forEach(file => {
|
|
118
|
-
logger.dim(` - ${file}`);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
logger.blank();
|
|
122
|
-
logger.success('Standards sync complete!');
|
|
123
|
-
logger.dim('Commit these changes with a sync: message.');
|
|
124
|
-
|
|
125
|
-
} catch (error) {
|
|
126
|
-
spinner.fail('Sync failed');
|
|
127
|
-
logger.error(error.message);
|
|
128
|
-
process.exit(1);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Group decisions by category
|
|
134
|
-
*/
|
|
135
|
-
function groupByCategory(decisions) {
|
|
136
|
-
const categories = {
|
|
137
|
-
'coding': [],
|
|
138
|
-
'architecture': [],
|
|
139
|
-
'azure': [],
|
|
140
|
-
'integrations': [],
|
|
141
|
-
'ui-ux': []
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
decisions.forEach(decision => {
|
|
145
|
-
const category = decision.category || 'coding';
|
|
146
|
-
if (categories[category]) {
|
|
147
|
-
categories[category].push(decision);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
return categories;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Format category name
|
|
156
|
-
*/
|
|
157
|
-
function formatCategory(category) {
|
|
158
|
-
const names = {
|
|
159
|
-
'coding': 'Coding Standards',
|
|
160
|
-
'architecture': 'Architecture Patterns',
|
|
161
|
-
'azure': 'Azure & Infrastructure',
|
|
162
|
-
'integrations': 'Integration Patterns',
|
|
163
|
-
'ui-ux': 'UI/UX Standards'
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
return names[category] || category;
|
|
167
|
-
}
|
|
@@ -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
|
-
}
|