@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
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Version Bump Script for MORPH-SPEC Framework
|
|
5
|
+
*
|
|
6
|
+
* Updates the version number across all files that contain it.
|
|
7
|
+
* Single source of truth: package.json
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node scripts/bump-version.js patch # 4.8.0 → 4.8.1
|
|
11
|
+
* node scripts/bump-version.js minor # 4.8.0 → 4.9.0
|
|
12
|
+
* node scripts/bump-version.js major # 4.8.0 → 5.0.0
|
|
13
|
+
* node scripts/bump-version.js 4.9.0 # explicit version
|
|
14
|
+
* node scripts/bump-version.js --dry-run patch # preview changes
|
|
15
|
+
*
|
|
16
|
+
* npm script:
|
|
17
|
+
* npm run version:bump -- patch
|
|
18
|
+
* npm run version:bump -- --dry-run minor
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
22
|
+
import { join, dirname } from 'path';
|
|
23
|
+
import { fileURLToPath } from 'url';
|
|
24
|
+
import { glob } from 'glob';
|
|
25
|
+
|
|
26
|
+
// ── Exported helpers (used by tests) ─────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compute a new version from a current version and bump type.
|
|
30
|
+
* @param {string} current - Current semver (e.g. "4.8.0")
|
|
31
|
+
* @param {string} type - "patch", "minor", "major", or explicit "X.Y.Z"
|
|
32
|
+
* @returns {string} New version string
|
|
33
|
+
*/
|
|
34
|
+
export function bumpVersion(current, type) {
|
|
35
|
+
const [major, minor, patch] = current.split('.').map(Number);
|
|
36
|
+
switch (type) {
|
|
37
|
+
case 'major': return `${major + 1}.0.0`;
|
|
38
|
+
case 'minor': return `${major}.${minor + 1}.0`;
|
|
39
|
+
case 'patch': return `${major}.${minor}.${patch + 1}`;
|
|
40
|
+
default: {
|
|
41
|
+
if (/^\d+\.\d+\.\d+$/.test(type)) return type;
|
|
42
|
+
throw new Error(`Invalid version or bump type: "${type}". Expected: patch, minor, major, or X.Y.Z`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function escapeRegex(str) {
|
|
48
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Build the list of file updates for a version bump.
|
|
53
|
+
* @param {string} rootDir - Project root directory
|
|
54
|
+
* @param {string} currentVersion - Current version string
|
|
55
|
+
* @param {string} newVersion - Target version string
|
|
56
|
+
* @returns {Array<{file: string, replacements: Array<{pattern: RegExp, replacement: string}>}>}
|
|
57
|
+
*/
|
|
58
|
+
export function buildFileUpdates(rootDir, currentVersion, newVersion) {
|
|
59
|
+
const cv = escapeRegex(currentVersion);
|
|
60
|
+
|
|
61
|
+
const updates = [
|
|
62
|
+
{
|
|
63
|
+
file: 'package.json',
|
|
64
|
+
replacements: [
|
|
65
|
+
{ pattern: new RegExp(`"version":\\s*"${cv}"`), replacement: `"version": "${newVersion}"` },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
file: 'claude-plugin.json',
|
|
70
|
+
replacements: [
|
|
71
|
+
{ pattern: new RegExp(`"version":\\s*"${cv}"`), replacement: `"version": "${newVersion}"` },
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
file: 'README.md',
|
|
76
|
+
replacements: [
|
|
77
|
+
{ pattern: new RegExp(`\\*\\*Version:\\*\\*\\s*${cv}`), replacement: `**Version:** ${newVersion}` },
|
|
78
|
+
{ pattern: new RegExp(`morph-spec v${cv}`), replacement: `morph-spec v${newVersion}` },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
file: 'docs/ARCHITECTURE.md',
|
|
83
|
+
replacements: [
|
|
84
|
+
{ pattern: new RegExp(`morph-spec v${cv}`, 'g'), replacement: `morph-spec v${newVersion}` },
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
file: 'docs/CHEATSHEET.md',
|
|
89
|
+
replacements: [
|
|
90
|
+
{ pattern: new RegExp(`morph-spec v${cv}`), replacement: `morph-spec v${newVersion}` },
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
file: 'docs/COMMAND-FLOWS.md',
|
|
95
|
+
replacements: [
|
|
96
|
+
{ pattern: new RegExp(`Version:\\s*${cv}`), replacement: `Version: ${newVersion}` },
|
|
97
|
+
{ pattern: new RegExp(`morph-spec v${cv}`), replacement: `morph-spec v${newVersion}` },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
file: 'docs/QUICKSTART.md',
|
|
102
|
+
replacements: [
|
|
103
|
+
{ pattern: new RegExp(`morph-spec v${cv}`), replacement: `morph-spec v${newVersion}` },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
file: 'framework/hooks/dev/guard-version-numbers.js',
|
|
108
|
+
replacements: [
|
|
109
|
+
{ pattern: new RegExp(`MORPH-SPEC v${cv}`), replacement: `MORPH-SPEC v${newVersion}` },
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
// Skill files (cliVersion in YAML frontmatter)
|
|
115
|
+
const skillFiles = glob.sync('framework/skills/level-1-workflows/*/SKILL.md', { cwd: rootDir });
|
|
116
|
+
for (const sf of skillFiles) {
|
|
117
|
+
updates.push({
|
|
118
|
+
file: sf,
|
|
119
|
+
replacements: [
|
|
120
|
+
{ pattern: new RegExp(`cliVersion:\\s*"${cv}"`), replacement: `cliVersion: "${newVersion}"` },
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return updates;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Apply version updates to files on disk.
|
|
130
|
+
* @param {string} rootDir - Project root directory
|
|
131
|
+
* @param {Array} fileUpdates - From buildFileUpdates()
|
|
132
|
+
* @param {{ dryRun?: boolean }} options
|
|
133
|
+
* @returns {{ updatedCount: number, replacementCount: number, warnings: string[] }}
|
|
134
|
+
*/
|
|
135
|
+
export function applyUpdates(rootDir, fileUpdates, { dryRun = false } = {}) {
|
|
136
|
+
let updatedCount = 0;
|
|
137
|
+
let replacementCount = 0;
|
|
138
|
+
const warnings = [];
|
|
139
|
+
|
|
140
|
+
for (const { file, replacements } of fileUpdates) {
|
|
141
|
+
const fullPath = join(rootDir, file);
|
|
142
|
+
|
|
143
|
+
if (!existsSync(fullPath)) {
|
|
144
|
+
warnings.push(`SKIP ${file} (file not found)`);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let content = readFileSync(fullPath, 'utf-8');
|
|
149
|
+
let fileChanged = false;
|
|
150
|
+
|
|
151
|
+
for (const { pattern, replacement } of replacements) {
|
|
152
|
+
if (pattern.test(content)) {
|
|
153
|
+
content = content.replace(pattern, replacement);
|
|
154
|
+
fileChanged = true;
|
|
155
|
+
replacementCount++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (fileChanged) {
|
|
160
|
+
if (!dryRun) {
|
|
161
|
+
writeFileSync(fullPath, content, 'utf-8');
|
|
162
|
+
}
|
|
163
|
+
updatedCount++;
|
|
164
|
+
} else {
|
|
165
|
+
warnings.push(`${file} (no matches — pattern may have changed)`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return { updatedCount, replacementCount, warnings };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── CLI entry point ──────────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
175
|
+
const isMainModule = process.argv[1]?.replace(/\\/g, '/').endsWith('scripts/bump-version.js');
|
|
176
|
+
|
|
177
|
+
if (isMainModule) {
|
|
178
|
+
const ROOT = join(__dirname, '..');
|
|
179
|
+
const args = process.argv.slice(2);
|
|
180
|
+
const dryRun = args.includes('--dry-run');
|
|
181
|
+
const filtered = args.filter(a => a !== '--dry-run');
|
|
182
|
+
|
|
183
|
+
if (filtered.length === 0) {
|
|
184
|
+
console.error(
|
|
185
|
+
'Usage: node scripts/bump-version.js [--dry-run] <patch|minor|major|X.Y.Z>'
|
|
186
|
+
);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const input = filtered[0];
|
|
191
|
+
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
|
192
|
+
const currentVersion = pkg.version;
|
|
193
|
+
|
|
194
|
+
let newVersion;
|
|
195
|
+
try {
|
|
196
|
+
newVersion = bumpVersion(currentVersion, input);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
console.error(err.message);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (newVersion === currentVersion) {
|
|
203
|
+
console.log(`Version is already ${currentVersion}. Nothing to do.`);
|
|
204
|
+
process.exit(0);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.log(`\nBumping version: ${currentVersion} → ${newVersion}`);
|
|
208
|
+
if (dryRun) console.log('(dry run — no files will be modified)\n');
|
|
209
|
+
else console.log('');
|
|
210
|
+
|
|
211
|
+
const fileUpdates = buildFileUpdates(ROOT, currentVersion, newVersion);
|
|
212
|
+
const result = applyUpdates(ROOT, fileUpdates, { dryRun });
|
|
213
|
+
|
|
214
|
+
for (const file of fileUpdates) {
|
|
215
|
+
const fullPath = join(ROOT, file.file);
|
|
216
|
+
if (existsSync(fullPath)) {
|
|
217
|
+
const content = readFileSync(fullPath, 'utf-8');
|
|
218
|
+
const hasMatch = file.replacements.some(r =>
|
|
219
|
+
dryRun
|
|
220
|
+
? new RegExp(escapeRegex(currentVersion)).test(content)
|
|
221
|
+
: new RegExp(escapeRegex(newVersion)).test(content)
|
|
222
|
+
);
|
|
223
|
+
if (hasMatch) console.log(` ✓ ${file.file}`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
console.log('');
|
|
228
|
+
if (result.warnings.length > 0) {
|
|
229
|
+
console.log('Warnings:');
|
|
230
|
+
for (const w of result.warnings) console.log(` ⚠ ${w}`);
|
|
231
|
+
console.log('');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log(
|
|
235
|
+
`${dryRun ? 'Would update' : 'Updated'} ${result.updatedCount} files (${result.replacementCount} replacements).`
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (dryRun) {
|
|
239
|
+
console.log('\nRe-run without --dry-run to apply changes.');
|
|
240
|
+
} else {
|
|
241
|
+
console.log(`\nVersion is now ${newVersion}.`);
|
|
242
|
+
console.log('Next steps:');
|
|
243
|
+
console.log(' 1. Review changes: git diff');
|
|
244
|
+
console.log(` 2. Commit: git commit -am "chore: bump version to ${newVersion}"`);
|
|
245
|
+
console.log(` 3. Tag: git tag v${newVersion}`);
|
|
246
|
+
console.log(' 4. Publish: npm publish');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dev Hooks Installer for MORPH-SPEC Framework Codebase
|
|
5
|
+
*
|
|
6
|
+
* Installs development-only hooks into .claude/settings.local.json.
|
|
7
|
+
* These hooks enforce quality standards when developing the framework itself:
|
|
8
|
+
* - Version number guard (no hardcoded versions in .md files)
|
|
9
|
+
* - Standard format validator (required metadata headers)
|
|
10
|
+
* - Skill frontmatter validator (required YAML fields)
|
|
11
|
+
* - Template registry sync advisory
|
|
12
|
+
* - Standards registry sync advisory
|
|
13
|
+
* - Sync health check advisory on Stop
|
|
14
|
+
*
|
|
15
|
+
* Usage: node scripts/install-dev-hooks.js
|
|
16
|
+
*
|
|
17
|
+
* Dev hooks use _morph_dev:true marker (not _morph:true) so they survive
|
|
18
|
+
* `morph-spec init/update` reinstalls, which only remove _morph:true entries.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
22
|
+
import { existsSync } from 'fs';
|
|
23
|
+
import { join } from 'path';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Dev hook definitions.
|
|
27
|
+
* Commands reference framework/hooks/dev/ directly (not .morph/framework/)
|
|
28
|
+
* since they only run in the framework repo where this path exists.
|
|
29
|
+
*/
|
|
30
|
+
const DEV_HOOKS = [
|
|
31
|
+
{
|
|
32
|
+
event: 'PreToolUse',
|
|
33
|
+
matcher: 'Write|Edit',
|
|
34
|
+
hooks: [
|
|
35
|
+
{ type: 'command', command: 'node framework/hooks/dev/guard-version-numbers.js' },
|
|
36
|
+
{ type: 'command', command: 'node framework/hooks/dev/validate-standard-format.js' },
|
|
37
|
+
{ type: 'command', command: 'node framework/hooks/dev/validate-skill-format.js' },
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
event: 'PostToolUse',
|
|
42
|
+
matcher: 'Write',
|
|
43
|
+
hooks: [
|
|
44
|
+
{ type: 'command', command: 'node framework/hooks/dev/sync-template-registry.js' },
|
|
45
|
+
{ type: 'command', command: 'node framework/hooks/dev/sync-standards-registry.js' },
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
event: 'Stop',
|
|
50
|
+
matcher: null,
|
|
51
|
+
hooks: [
|
|
52
|
+
{ type: 'command', command: 'node framework/hooks/dev/check-sync-health.js' },
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Install dev hooks into .claude/settings.local.json.
|
|
59
|
+
* Preserves _morph:true entries and user hooks.
|
|
60
|
+
* Removes old _morph_dev:true entries before installing (clean slate).
|
|
61
|
+
*
|
|
62
|
+
* @param {string} [projectPath] - Project root (defaults to cwd)
|
|
63
|
+
* @returns {Promise<{ installed: number }>}
|
|
64
|
+
*/
|
|
65
|
+
export async function installDevHooks(projectPath) {
|
|
66
|
+
const root = projectPath || process.cwd();
|
|
67
|
+
const claudeDir = join(root, '.claude');
|
|
68
|
+
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
69
|
+
|
|
70
|
+
// Read existing settings
|
|
71
|
+
let settings = {};
|
|
72
|
+
if (existsSync(settingsPath)) {
|
|
73
|
+
try {
|
|
74
|
+
settings = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
75
|
+
} catch {
|
|
76
|
+
settings = {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
settings.hooks = settings.hooks || {};
|
|
81
|
+
|
|
82
|
+
// Remove old dev hooks (clean slate)
|
|
83
|
+
for (const [event, entries] of Object.entries(settings.hooks)) {
|
|
84
|
+
if (!Array.isArray(entries)) continue;
|
|
85
|
+
settings.hooks[event] = entries.filter(entry => entry._morph_dev !== true);
|
|
86
|
+
if (settings.hooks[event].length === 0) {
|
|
87
|
+
delete settings.hooks[event];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Install dev hooks
|
|
92
|
+
let installed = 0;
|
|
93
|
+
for (const hookDef of DEV_HOOKS) {
|
|
94
|
+
const { event, matcher, hooks } = hookDef;
|
|
95
|
+
|
|
96
|
+
if (!settings.hooks[event]) {
|
|
97
|
+
settings.hooks[event] = [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const entry = { _morph_dev: true };
|
|
101
|
+
if (matcher) {
|
|
102
|
+
entry.matcher = matcher;
|
|
103
|
+
}
|
|
104
|
+
entry.hooks = hooks.map(h => ({ type: h.type, command: h.command }));
|
|
105
|
+
|
|
106
|
+
settings.hooks[event].push(entry);
|
|
107
|
+
installed++;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Ensure .claude directory exists
|
|
111
|
+
if (!existsSync(claudeDir)) {
|
|
112
|
+
await mkdir(claudeDir, { recursive: true });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
116
|
+
return { installed };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get the dev hooks definitions (for testing/inspection).
|
|
121
|
+
* @returns {Array}
|
|
122
|
+
*/
|
|
123
|
+
export function getDevHookDefinitions() {
|
|
124
|
+
return DEV_HOOKS;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// CLI entry point
|
|
128
|
+
const isMainModule = process.argv[1]?.replace(/\\/g, '/').endsWith('scripts/install-dev-hooks.js');
|
|
129
|
+
if (isMainModule) {
|
|
130
|
+
try {
|
|
131
|
+
const result = await installDevHooks();
|
|
132
|
+
console.log(`Installed ${result.installed} dev hooks into .claude/settings.local.json`);
|
|
133
|
+
console.log('Dev hooks are active for framework development only (_morph_dev: true).');
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('Failed to install dev hooks:', err.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
}
|
package/src/commands/index.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* All Commands - Category Exports
|
|
3
|
-
*
|
|
4
|
-
* Commands organized by functional category.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './
|
|
14
|
-
export * from './tasks/index.js';
|
|
15
|
-
export * from './agents/index.js';
|
|
16
|
-
export * from './utils/index.js';
|
|
1
|
+
/**
|
|
2
|
+
* All Commands - Category Exports
|
|
3
|
+
*
|
|
4
|
+
* Commands organized by functional category.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './state/index.js';
|
|
8
|
+
export * from './validation/index.js';
|
|
9
|
+
export * from './templates/index.js';
|
|
10
|
+
export * from './project/index.js';
|
|
11
|
+
export * from './tasks/index.js';
|
|
12
|
+
export * from './agents/index.js';
|
|
13
|
+
export * from './utils/index.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
|
-
import { platform } from 'os';
|
|
3
|
+
import { platform, homedir } from 'os';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { logger } from '../../utils/logger.js';
|
|
@@ -13,6 +13,18 @@ import {
|
|
|
13
13
|
import { resetMorphSettings } from '../../utils/claude-settings-manager.js';
|
|
14
14
|
|
|
15
15
|
const isWindows = platform() === 'win32';
|
|
16
|
+
/**
|
|
17
|
+
* Check which required Claude Code plugins are installed.
|
|
18
|
+
* @param {Object} pluginsData - The `plugins` object from installed_plugins.json
|
|
19
|
+
* @returns {{ superpowers: boolean, context7: boolean }}
|
|
20
|
+
*/
|
|
21
|
+
export function checkInstalledPlugins(pluginsData) {
|
|
22
|
+
const REQUIRED = ['superpowers', 'context7'];
|
|
23
|
+
return Object.fromEntries(
|
|
24
|
+
REQUIRED.map(name => [name, `${name}@claude-plugins-official` in (pluginsData || {})])
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
|
|
17
29
|
/**
|
|
18
30
|
* Check if morph-spec command is in PATH
|
|
@@ -72,18 +84,20 @@ const REQUIRED_LIB_FILES = [
|
|
|
72
84
|
'src/lib/trust/trust-manager.js'
|
|
73
85
|
];
|
|
74
86
|
|
|
75
|
-
// command files
|
|
87
|
+
// command files (current CLI surface after radical simplification)
|
|
76
88
|
const REQUIRED_COMMAND_FILES = [
|
|
77
|
-
'src/commands/
|
|
78
|
-
'src/commands/
|
|
79
|
-
'src/commands/
|
|
80
|
-
'src/commands/
|
|
81
|
-
'src/commands/
|
|
82
|
-
'src/commands/
|
|
83
|
-
'src/commands/
|
|
84
|
-
'src/commands/
|
|
85
|
-
'src/commands/
|
|
86
|
-
'src/commands/trust/trust.js'
|
|
89
|
+
'src/commands/project/init.js',
|
|
90
|
+
'src/commands/project/update.js',
|
|
91
|
+
'src/commands/project/doctor.js',
|
|
92
|
+
'src/commands/project/status.js',
|
|
93
|
+
'src/commands/project/tutorial.js',
|
|
94
|
+
'src/commands/state/state.js',
|
|
95
|
+
'src/commands/state/advance-phase.js',
|
|
96
|
+
'src/commands/state/approve.js',
|
|
97
|
+
'src/commands/tasks/task.js',
|
|
98
|
+
'src/commands/trust/trust.js',
|
|
99
|
+
'src/commands/validation/validate-feature.js',
|
|
100
|
+
'src/commands/templates/template-render.js'
|
|
87
101
|
];
|
|
88
102
|
|
|
89
103
|
// HOP templates (meta-prompts)
|
|
@@ -227,9 +241,9 @@ async function doctorFullCommand(frameworkRoot) {
|
|
|
227
241
|
if (await pathExists(statePath)) {
|
|
228
242
|
try {
|
|
229
243
|
const state = JSON.parse(await fs.readFile(statePath, 'utf8'));
|
|
230
|
-
const isCurrent = state.version === '
|
|
244
|
+
const isCurrent = state.version === '5.0.0';
|
|
231
245
|
check(`state.json schema (${state.version})`, isCurrent, true,
|
|
232
|
-
isCurrent ? '' :
|
|
246
|
+
isCurrent ? '' : `expected 5.0.0, found ${state.version} — run any CLI command to auto-migrate`);
|
|
233
247
|
} catch {
|
|
234
248
|
check('state.json parse', false, false, 'invalid JSON');
|
|
235
249
|
}
|
|
@@ -558,6 +572,78 @@ export async function doctorCommand(options = {}) {
|
|
|
558
572
|
checks.push({ name: '.claude/agents/', status: 'warn', msg: 'missing — run morph-spec update' });
|
|
559
573
|
hasWarnings = true;
|
|
560
574
|
}
|
|
575
|
+
// ── Hook health: verify hook scripts exist ───────────────────────────────
|
|
576
|
+
const settingsLocalPath = join(claudePath, 'settings.local.json');
|
|
577
|
+
if (await pathExists(settingsLocalPath)) {
|
|
578
|
+
try {
|
|
579
|
+
const settings = JSON.parse(await fs.readFile(settingsLocalPath, 'utf8'));
|
|
580
|
+
const hookCommands = [];
|
|
581
|
+
for (const eventHooks of Object.values(settings.hooks || {})) {
|
|
582
|
+
for (const group of (Array.isArray(eventHooks) ? eventHooks : [])) {
|
|
583
|
+
for (const h of (group.hooks || [])) {
|
|
584
|
+
if (h.type === 'command' && h.command) hookCommands.push(h.command);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const hookPathRe = /\$CLAUDE_PROJECT_DIR\/([^\s"]+\.js)/;
|
|
589
|
+
const missingHooks = [];
|
|
590
|
+
for (const cmd of hookCommands) {
|
|
591
|
+
const m = cmd.match(hookPathRe);
|
|
592
|
+
if (m && !(await pathExists(join(targetPath, m[1])))) {
|
|
593
|
+
missingHooks.push(m[1].split('/').pop());
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (missingHooks.length === 0) {
|
|
597
|
+
checks.push({ name: 'hook scripts', status: 'ok', msg: `${hookCommands.length} hooks configured` });
|
|
598
|
+
} else {
|
|
599
|
+
checks.push({ name: 'hook scripts', status: 'warn', msg: `missing: ${missingHooks.join(', ')} — run morph-spec update` });
|
|
600
|
+
hasWarnings = true;
|
|
601
|
+
}
|
|
602
|
+
} catch {
|
|
603
|
+
checks.push({ name: 'hook scripts', status: 'warn', msg: 'could not parse settings.local.json' });
|
|
604
|
+
hasWarnings = true;
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
checks.push({ name: 'hook scripts', status: 'warn', msg: 'settings.local.json missing — run morph-spec init' });
|
|
608
|
+
hasWarnings = true;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// ── Skills cliVersion: warn if installed skills reference older CLI ──────
|
|
612
|
+
try {
|
|
613
|
+
const cliVersion = getInstalledCLIVersion();
|
|
614
|
+
if (cliVersion) {
|
|
615
|
+
const skillDirsForVersion = await fs.readdir(skillsPath);
|
|
616
|
+
const staleSkills = [];
|
|
617
|
+
for (const skillDir of skillDirsForVersion) {
|
|
618
|
+
const skillMdPath = join(skillsPath, skillDir, 'SKILL.md');
|
|
619
|
+
if (!(await pathExists(skillMdPath))) continue;
|
|
620
|
+
const content = await fs.readFile(skillMdPath, 'utf8');
|
|
621
|
+
const m = content.match(/^cliVersion:\s*"?([^"\n]+)"?/m);
|
|
622
|
+
if (m && m[1].trim() !== cliVersion) {
|
|
623
|
+
staleSkills.push(skillDir);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (staleSkills.length === 0) {
|
|
627
|
+
checks.push({ name: 'skill cliVersion', status: 'ok' });
|
|
628
|
+
} else {
|
|
629
|
+
checks.push({ name: 'skill cliVersion', status: 'warn', msg: `${staleSkills.length} skill(s) behind CLI v${cliVersion} — run morph-spec update` });
|
|
630
|
+
hasWarnings = true;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
} catch { /* non-fatal */ }
|
|
634
|
+
|
|
635
|
+
// ── Claude Code Plugins ──────────────────────────────────────────────────
|
|
636
|
+
console.log(chalk.cyan('\n Claude Code Plugins (required for /morph-init)'));
|
|
637
|
+
const pluginsFile = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');
|
|
638
|
+
let pluginData = { plugins: {} };
|
|
639
|
+
try {
|
|
640
|
+
pluginData = JSON.parse(await fs.readFile(pluginsFile, 'utf8'));
|
|
641
|
+
} catch { /* file may not exist */ }
|
|
642
|
+
const pluginStatus = checkInstalledPlugins(pluginData.plugins || {});
|
|
643
|
+
check('superpowers plugin', pluginStatus.superpowers, false,
|
|
644
|
+
'Run: morph-spec install-plugin superpowers');
|
|
645
|
+
check('context7 plugin', pluginStatus.context7, false,
|
|
646
|
+
'Run: morph-spec install-plugin context7');
|
|
561
647
|
} else {
|
|
562
648
|
checks.push({ name: '.claude/', status: 'warn', msg: 'incomplete structure' });
|
|
563
649
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project-Level Commands
|
|
3
|
-
*/
|
|
4
|
-
export { initCommand } from './init.js';
|
|
5
|
-
export { doctorCommand } from './doctor.js';
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
8
|
-
export { detectAgentsCommand } from './detect-agents.js';
|
|
9
|
-
export { syncCommand } from './sync.js';
|
|
10
|
-
export { updateCommand } from './update.js';
|
|
1
|
+
/**
|
|
2
|
+
* Project-Level Commands
|
|
3
|
+
*/
|
|
4
|
+
export { initCommand } from './init.js';
|
|
5
|
+
export { doctorCommand } from './doctor.js';
|
|
6
|
+
export { updateCommand } from './update.js';
|
|
7
|
+
export { tutorialCommand } from './tutorial.js';
|