@polymorphism-tech/morph-spec 4.3.6 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.morph/.morphversion +3 -3
- package/.morph/analytics/threads-log.jsonl +44 -9
- package/.morph/config/config.json +2 -3
- package/.morph/framework/standards/STANDARDS.json +812 -0
- package/.morph/{standards → framework/standards}/ai-agents/team-orchestration.md +3 -3
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +384 -0
- package/.morph/{templates → framework/templates}/README.md +17 -17
- package/.morph/{templates → framework/templates}/REGISTRY.json +48 -233
- package/.morph/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
- package/.morph/{templates → framework/templates}/context/CONTEXT-FEATURE.md +1 -1
- package/.morph/{templates → framework/templates}/context/CONTEXT.md +3 -3
- package/.morph/framework/templates/docs/clarifications.md +253 -0
- package/.morph/framework/templates/docs/onboarding.md +123 -0
- package/.morph/framework/templates/docs/schema-analysis.md +119 -0
- package/.morph/{templates → framework/templates}/docs/spec.md +149 -149
- package/.morph/framework/templates/docs/ui-components.md +124 -0
- package/.morph/framework/templates/docs/ui-design-system.md +76 -0
- package/.morph/framework/templates/docs/ui-flows.md +167 -0
- package/.morph/framework/templates/docs/ui-mockups.md +98 -0
- package/.morph/{templates → framework/templates}/examples/spec-examples.md +1 -1
- package/.morph/{templates → framework/templates}/infrastructure/github/README.md +11 -11
- package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
- package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-worker.md +2 -2
- package/.morph/{templates → framework/templates}/meta-prompts/validators/pre-commit-validator.md +1 -1
- package/.morph/logs/tool-failures.log +51 -0
- package/.morph/memory/pre-compact-2026-02-22T17-01-01-658Z.json +16 -0
- package/.morph/state.json +1 -1
- package/CLAUDE.md +20 -119
- package/README.md +20 -18
- package/bin/detect-agents.js +1 -1
- package/bin/morph-spec.js +116 -266
- package/bin/task-manager.cjs +2 -2
- package/bin/validate.js +1 -1
- package/claude-plugin.json +14 -0
- package/docs/claude-alignment-report.md +137 -0
- package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +512 -0
- package/docs/plans/2026-02-22-claude-settings.md +515 -0
- package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +728 -0
- package/docs/plans/2026-02-22-morph-spec-next.md +478 -0
- package/docs/plans/2026-02-22-native-alignment-design.md +199 -0
- package/docs/plans/2026-02-22-native-alignment-impl.md +925 -0
- package/docs/plans/2026-02-22-native-enrichment-design.md +244 -0
- package/docs/plans/2026-02-22-native-enrichment.md +735 -0
- package/framework/CLAUDE.md +77 -0
- package/framework/commands/morph-apply.md +9 -9
- package/framework/commands/morph-archive.md +8 -8
- package/framework/commands/morph-infra.md +1 -1
- package/framework/commands/morph-proposal.md +9 -9
- package/framework/commands/morph-status.md +3 -3
- package/framework/commands/morph-troubleshoot.md +1 -1
- package/framework/hooks/README.md +201 -282
- package/framework/hooks/claude-code/notification/approval-reminder.js +52 -0
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +83 -0
- package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +42 -0
- package/framework/hooks/claude-code/pre-compact/save-morph-context.js +61 -0
- package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +71 -0
- package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +58 -0
- package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +64 -0
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +94 -0
- package/framework/hooks/claude-code/statusline.py +239 -0
- package/framework/hooks/claude-code/statusline.sh +7 -0
- package/framework/hooks/claude-code/stop/validate-completion.js +88 -0
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +91 -0
- package/framework/hooks/shared/hook-response.js +45 -0
- package/framework/hooks/shared/phase-utils.js +129 -0
- package/framework/hooks/shared/state-reader.js +138 -0
- package/framework/hooks/shared/stdin-reader.js +26 -0
- package/framework/phases.json +145 -0
- package/framework/rules/csharp-standards.md +10 -0
- package/framework/rules/frontend-standards.md +14 -0
- package/framework/rules/infrastructure-standards.md +13 -0
- package/framework/rules/morph-workflow.md +86 -0
- package/framework/rules/testing-standards.md +11 -0
- package/framework/skills/level-0-meta/brainstorming.md +133 -0
- package/framework/skills/level-0-meta/code-review.md +12 -4
- package/framework/skills/level-0-meta/mcp-registry.json +207 -0
- package/framework/skills/level-0-meta/morph-checklist.md +9 -1
- package/framework/skills/level-0-meta/simulation-checklist.md +9 -1
- package/framework/skills/level-0-meta/tool-usage-guide.md +335 -0
- package/framework/skills/level-0-meta/verification-before-completion.md +145 -0
- package/framework/skills/level-1-workflows/morph-replicate.md +9 -1
- package/framework/skills/level-1-workflows/phase-clarify.md +65 -4
- package/framework/skills/level-1-workflows/phase-codebase-analysis.md +182 -0
- package/framework/skills/level-1-workflows/phase-design.md +342 -80
- package/framework/skills/level-1-workflows/phase-implement.md +254 -0
- package/framework/skills/level-1-workflows/phase-setup.md +76 -10
- package/framework/skills/level-1-workflows/phase-tasks.md +88 -7
- package/framework/skills/level-1-workflows/phase-uiux.md +95 -17
- package/framework/skills/level-2-domains/ai-agents/ai-system-architect.md +8 -1
- package/framework/skills/level-2-domains/architecture/po-pm-advisor.md +8 -1
- package/framework/skills/level-2-domains/architecture/prompt-engineer.md +8 -1
- package/framework/skills/level-2-domains/architecture/seo-growth-hacker.md +8 -1
- package/framework/skills/level-2-domains/architecture/standards-architect.md +11 -4
- package/framework/skills/level-2-domains/backend/api-designer.md +8 -1
- package/framework/skills/level-2-domains/backend/dotnet-senior.md +8 -1
- package/framework/skills/level-2-domains/backend/ef-modeler.md +8 -1
- package/framework/skills/level-2-domains/backend/hangfire-orchestrator.md +9 -2
- package/framework/skills/level-2-domains/backend/ms-agent-expert.md +8 -1
- package/framework/skills/level-2-domains/frontend/blazor-builder.md +8 -1
- package/framework/skills/level-2-domains/frontend/nextjs-expert.md +8 -1
- package/framework/skills/level-2-domains/frontend/ui-ux-designer.md +9 -2
- package/framework/skills/level-2-domains/infrastructure/azure-architect.md +8 -1
- package/framework/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +8 -1
- package/framework/skills/level-2-domains/infrastructure/bicep-architect.md +8 -1
- package/framework/skills/level-2-domains/infrastructure/container-specialist.md +8 -1
- package/framework/skills/level-2-domains/infrastructure/devops-engineer.md +8 -1
- package/framework/skills/level-2-domains/integrations/asaas-financial.md +8 -1
- package/framework/skills/level-2-domains/integrations/azure-identity.md +8 -1
- package/framework/skills/level-2-domains/integrations/clerk-auth.md +8 -1
- package/framework/skills/level-2-domains/integrations/{hangfire-orchestrator.md → hangfire-integration.md} +8 -1
- package/framework/skills/level-2-domains/integrations/resend-email.md +8 -1
- package/framework/skills/level-2-domains/quality/code-analyzer.md +10 -3
- package/framework/skills/level-2-domains/quality/testing-specialist.md +8 -1
- package/framework/standards/STANDARDS.json +812 -0
- package/framework/standards/ai-agents/team-orchestration.md +3 -3
- package/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -0
- package/framework/standards/integration/mcp/mcp-tools.md +384 -0
- package/framework/templates/README.md +17 -17
- package/framework/templates/REGISTRY.json +48 -233
- package/framework/templates/code/dotnet/contracts/contracts.cs.hbs +172 -0
- package/framework/templates/context/CONTEXT-FEATURE.md +1 -1
- package/framework/templates/context/CONTEXT.md +3 -3
- package/framework/templates/docs/clarifications.md +253 -0
- package/framework/templates/docs/onboarding.md +123 -0
- package/framework/templates/docs/schema-analysis.md +119 -0
- package/framework/templates/docs/spec.md +149 -149
- package/framework/templates/docs/ui-components.md +124 -0
- package/framework/templates/docs/ui-design-system.md +76 -0
- package/framework/templates/docs/ui-flows.md +167 -0
- package/framework/templates/docs/ui-mockups.md +98 -0
- package/framework/templates/docs/user-stories.md +34 -0
- package/framework/templates/examples/spec-examples.md +1 -1
- package/framework/templates/infrastructure/github/README.md +11 -11
- package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +2 -2
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +1 -1
- package/framework/workflows/configs/express.json +45 -0
- package/framework/workflows/configs/spec-only.json +43 -0
- package/framework/workflows/docs/enforcement-pipeline.md +8 -8
- package/framework/workflows/docs/full-morph.md +3 -3
- package/package.json +3 -2
- package/scripts/generate-refs.js +336 -0
- package/scripts/generate-standards-registry.js +44 -0
- package/scripts/validate-real.mjs +255 -0
- package/src/commands/feature/create-story.js +362 -361
- package/src/commands/feature/shard-spec.js +225 -224
- package/src/commands/feature/sprint-status.js +1 -1
- package/src/commands/generation/generate-onboarding.js +169 -0
- package/src/commands/generation/generate.js +2 -2
- package/src/commands/mcp/mcp-setup.js +315 -0
- package/src/commands/project/changes.js +66 -0
- package/src/commands/project/checkpoint.js +209 -0
- package/src/commands/project/cost.js +179 -0
- package/src/commands/project/diff.js +278 -0
- package/src/commands/project/doctor.js +55 -7
- package/src/commands/project/init.js +318 -76
- package/src/commands/project/revert.js +173 -0
- package/src/commands/project/standards.js +80 -0
- package/src/commands/project/status.js +376 -0
- package/src/commands/project/update-agents.js +23 -0
- package/src/commands/project/update.js +63 -30
- package/src/commands/state/advance-phase.js +4 -3
- package/src/commands/state/state.js +10 -3
- package/src/commands/state/validate-phase.js +19 -2
- package/src/commands/templates/template-customize.js +4 -4
- package/src/commands/templates/template-render.js +1 -1
- package/src/commands/templates/template-show.js +1 -1
- package/src/commands/validation/validate-feature.js +359 -0
- package/src/core/orchestrator.js +3 -38
- package/src/core/paths/output-schema.js +135 -0
- package/src/core/state/state-manager.js +831 -592
- package/src/core/templates/template-registry.js +2 -2
- package/src/core/workflows/workflow-detector.js +17 -1
- package/src/lib/agents/micro-agent-factory.js +1 -1
- package/src/lib/context/context-bundler.js +2 -1
- package/src/lib/detectors/claude-config-detector.js +392 -0
- package/src/lib/detectors/conversation-analyzer.js +4 -4
- package/src/lib/detectors/design-system-detector.js +6 -5
- package/src/lib/detectors/standards-generator.js +2 -2
- package/src/lib/generators/context-generator.js +539 -538
- package/src/lib/generators/recap-generator.js +1 -1
- package/src/lib/generators/settings-generator.js +210 -0
- package/src/lib/hooks/hook-executor.js +1 -1
- package/src/lib/installers/mcp-installer.js +299 -0
- package/src/lib/learning/learning-system.js +3 -3
- package/src/lib/orchestration/team-orchestrator.js +1 -1
- package/src/lib/standards/standards-context-injector.js +7 -7
- package/src/lib/threads/thread-coordinator.js +1 -1
- package/src/lib/troubleshooting/troubleshoot-grep.js +1 -1
- package/src/lib/validators/contracts/contract-compliance-validator.js +274 -273
- package/src/lib/validators/design-system/design-system-validator.js +1 -1
- package/src/lib/validators/spec-validator.js +258 -258
- package/src/lib/validators/validation-runner.js +270 -269
- package/src/utils/agents-installer.js +206 -0
- package/src/utils/claude-settings-manager.js +258 -0
- package/src/utils/file-copier.js +1 -1
- package/src/utils/hooks-installer.js +354 -28
- package/src/utils/skills-installer.js +74 -0
- package/.morph/project/context/detection-log.md +0 -16
- package/.morph/project/standards/inferred.md +0 -59
- package/framework/hooks/agent-stop/validate-and-continue.js +0 -96
- package/framework/hooks/agent-stop/validate-checkpoints.js +0 -101
- package/framework/hooks/agent-stop/validate-tests.js +0 -109
- package/framework/hooks/agent-teams/dispatch.js +0 -67
- package/framework/hooks/agent-teams/phase-advanced.js +0 -80
- package/framework/hooks/agent-teams/task-completed.js +0 -76
- package/framework/hooks/agent-teams/teammate-idle.js +0 -70
- package/src/commands/agents/agents-fuse.js +0 -97
- package/src/commands/agents/micro-agent.js +0 -112
- package/src/commands/agents/spawn-team.js +0 -237
- package/src/commands/agents/squad-template.js +0 -146
- package/src/commands/analytics/analytics.js +0 -176
- package/src/commands/context/context-prime.js +0 -63
- package/src/commands/context/core-four.js +0 -54
- package/src/commands/generation/generate-context.js +0 -40
- package/src/commands/project/detect-agents.js +0 -207
- package/src/commands/project/detect-workflow.js +0 -174
- package/src/commands/threads/thread-template.js +0 -103
- package/src/commands/threads/threads.js +0 -261
- package/src/commands/utils/session-summary.js +0 -291
- package/src/llm/analyzer.js +0 -215
- package/src/llm/few-shot-examples.js +0 -216
- package/src/llm/project-config-schema.json +0 -188
- package/src/llm/prompt-builder.js +0 -96
- /package/.morph/{project/context → context}/README.md +0 -0
- /package/.morph/{config → framework}/agents.json +0 -0
- /package/.morph/{standards → framework/standards}/ai-agents/blazor-ui.md +0 -0
- /package/.morph/{standards → framework/standards}/ai-agents/production.md +0 -0
- /package/.morph/{standards → framework/standards}/ai-agents/setup.md +0 -0
- /package/.morph/{standards → framework/standards}/ai-agents/workflows.md +0 -0
- /package/.morph/{standards → framework/standards}/architecture/ddd/aggregates.md +0 -0
- /package/.morph/{standards → framework/standards}/architecture/ddd/entities.md +0 -0
- /package/.morph/{standards → framework/standards}/architecture/ddd/value-objects.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/api/minimal-api.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/api/rest.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/api/validation.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/authentication/passkeys.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/database/ef-core.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/database/migrations.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/database/postgresql/database.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/database/repository-patterns.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/database/vector-search-rag.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/dotnet/async.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/dotnet/core.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/dotnet/di.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/dotnet/program-cs-checklist.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/integrations/asaas/asaas-api.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/integrations/clerk/clerk-auth.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/integrations/hangfire/hangfire-jobs.md +0 -0
- /package/.morph/{standards → framework/standards}/backend/integrations/resend/resend-email.md +0 -0
- /package/.morph/{standards → framework/standards}/context/analytics.md +0 -0
- /package/.morph/{standards → framework/standards}/context/bundles.md +0 -0
- /package/.morph/{standards → framework/standards}/context/priming.md +0 -0
- /package/.morph/{standards → framework/standards}/core/architecture.md +0 -0
- /package/.morph/{standards → framework/standards}/core/coding.md +0 -0
- /package/.morph/{standards → framework/standards}/core/git-branching-strategy.md +0 -0
- /package/.morph/{standards → framework/standards}/core/git.md +0 -0
- /package/.morph/{standards → framework/standards}/core/testing.md +0 -0
- /package/.morph/{standards → framework/standards}/data/nosql/blob-storage.md +0 -0
- /package/.morph/{standards → framework/standards}/data/nosql/cache/redis.md +0 -0
- /package/.morph/{standards → framework/standards}/data/nosql/cosmos-db.md +0 -0
- /package/.morph/{standards → framework/standards}/data/vector-search/azure-ai-search.md +0 -0
- /package/.morph/{standards → framework/standards}/data/vector-search/rag-chunking.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/design-checklist.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui-setup.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/fluent-ui.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/html-conversion.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/lifecycle.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/pitfalls.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/blazor/state.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/design-system/animations.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/design-system/naming.md +0 -0
- /package/.morph/{standards → framework/standards}/frontend/nextjs/nextjs-patterns.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/azure.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/bicep/bicep-patterns.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/azure-devops-setup.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/devops/local-development.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/services/functions.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/services/service-bus.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/azure/services/storage.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/docker/easypanel-deploy.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/supabase/mcp-setup.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-auth.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-pgvector.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-rls.md +0 -0
- /package/.morph/{standards → framework/standards}/infrastructure/supabase/supabase-storage.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/api/graphql.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/api/grpc.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/api/rest-design.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/event-driven/cqrs.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/event-driven/event-sourcing.md +0 -0
- /package/.morph/{standards → framework/standards}/integration/event-driven/service-bus.md +0 -0
- /package/.morph/{standards → framework/standards}/observability/logging.md +0 -0
- /package/.morph/{standards → framework/standards}/observability/metrics.md +0 -0
- /package/.morph/{standards → framework/standards}/observability/monitoring.md +0 -0
- /package/.morph/{standards → framework/standards}/observability/tracing.md +0 -0
- /package/.morph/{standards → framework/standards}/workflows/parallel-execution.md +0 -0
- /package/.morph/{standards → framework/standards}/workflows/thread-management.md +0 -0
- /package/.morph/{templates → framework/templates}/.idea/morph-templates.xml +0 -0
- /package/.morph/{templates → framework/templates}/.vscode/morph-templates.code-snippets +0 -0
- /package/.morph/{templates → framework/templates}/IDE-SNIPPETS.md +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/backend/repository.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/backend/service.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Commands.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Entities.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/Queries.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/README.md +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/api-contracts.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/contracts/contracts.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/database/migration.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/frontend/component.razor +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/jobs/agent.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/jobs/job.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/dotnet/test.cs +0 -0
- /package/.morph/{templates → framework/templates}/code/sql/rls-policy.sql +0 -0
- /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.sql +0 -0
- /package/.morph/{templates → framework/templates}/code/sql/supabase-migration.template.sql +0 -0
- /package/.morph/{templates → framework/templates}/code/typescript/contracts.ts +0 -0
- /package/.morph/{templates → framework/templates}/docs/proposal.md +0 -0
- /package/.morph/{templates → framework/templates}/examples/design-system-examples.md +0 -0
- /package/.morph/{templates → framework/templates}/feature/decisions.md +0 -0
- /package/.morph/{templates → framework/templates}/feature/recap.md +0 -0
- /package/.morph/{templates → framework/templates}/feature/tasks.md +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/Dockerfile.example +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/README.md +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/app-insights.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/app-service.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app-env.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/container-app.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy-checklist.md +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.ps1 +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/deploy.sh +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/key-vault.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/main.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.dev.json +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.prod.json +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/parameters.staging.json +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/sql-database.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/azure/storage.bicep +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/docker/Dockerfile.template +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/docker/docker-compose.template.yml +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-api.dockerfile +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/docker/dockerfile-web.dockerfile +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/docker/easypanel.template.json +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/actions/health-check/action.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -0
- /package/.morph/{templates → framework/templates}/integrations/asaas-client.cs +0 -0
- /package/.morph/{templates → framework/templates}/integrations/asaas-webhook.cs +0 -0
- /package/.morph/{templates → framework/templates}/integrations/azure-identity-config.cs +0 -0
- /package/.morph/{templates → framework/templates}/integrations/clerk-config.cs +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-agent.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/fusion/fusion-aggregator.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-retry.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-validation.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/hops/hop-wrapper.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/parallel-workers/parallel-coordinator.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/backend-squad.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/frontend-squad.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/squad-leaders/squad-leader.md +0 -0
- /package/.morph/{templates → framework/templates}/meta-prompts/validators/checkpoint-validator.md +0 -0
- /package/.morph/{templates → framework/templates}/saas/subscription.cs +0 -0
- /package/.morph/{templates → framework/templates}/saas/tenant.cs +0 -0
- /package/.morph/{templates → framework/templates}/state.template.json +0 -0
- /package/.morph/{templates → framework/templates}/ui/FluentDesignTheme.cs +0 -0
- /package/.morph/{templates → framework/templates}/ui/MudTheme.cs +0 -0
- /package/.morph/{templates → framework/templates}/ui/design-system.css +0 -0
- /package/framework/hooks/{commit-msg → git/commit-msg}/conventional-commits.sh +0 -0
- /package/framework/hooks/{pre-commit → git/pre-commit}/agents.sh +0 -0
- /package/framework/hooks/{pre-commit → git/pre-commit}/orchestrator.sh +0 -0
- /package/framework/hooks/{pre-commit → git/pre-commit}/specs.sh +0 -0
- /package/framework/hooks/{pre-push → git/pre-push}/run-tests.sh +0 -0
|
@@ -18,15 +18,26 @@ import {
|
|
|
18
18
|
createDirectoryLink
|
|
19
19
|
} from '../../utils/file-copier.js';
|
|
20
20
|
import { saveProjectMorphVersion, getInstalledCLIVersion } from '../../utils/version-checker.js';
|
|
21
|
-
import { installClaudeHooks } from '../../utils/
|
|
21
|
+
import { installClaudeHooks, installGlobalStatusline } from '../../utils/claude-settings-manager.js';
|
|
22
|
+
import { installSkills } from '../../utils/skills-installer.js';
|
|
23
|
+
import { installAgents, installDomainAgents } from '../../utils/agents-installer.js';
|
|
22
24
|
import { AutoContextOrchestrator } from '../../core/orchestrator.js';
|
|
23
25
|
import { detectClaudeCode } from '../../llm/environment-detector.js';
|
|
24
26
|
import inquirer from 'inquirer';
|
|
25
27
|
import { detectProject } from '../../lib/detectors/index.js';
|
|
28
|
+
import { detectClaudeConfig, mapMcpsToPhases, formatConfigSummary } from '../../lib/detectors/claude-config-detector.js';
|
|
29
|
+
import { generateSettings, saveIntegrations } from '../../lib/generators/settings-generator.js';
|
|
30
|
+
import {
|
|
31
|
+
orchestrateMcpSetup,
|
|
32
|
+
installAutoMcps,
|
|
33
|
+
installMcpWithCredentials,
|
|
34
|
+
generateSetupInstructions,
|
|
35
|
+
formatMcpStatusTable
|
|
36
|
+
} from '../../lib/installers/mcp-installer.js';
|
|
26
37
|
|
|
27
38
|
export async function initCommand(options) {
|
|
28
39
|
const targetPath = options.path || process.cwd();
|
|
29
|
-
const claudeMdPath = join(import.meta.dirname, '..', '..', '..', 'CLAUDE.md');
|
|
40
|
+
const claudeMdPath = join(import.meta.dirname, '..', '..', '..', 'framework', 'CLAUDE.md');
|
|
30
41
|
|
|
31
42
|
logger.header('MORPH-SPEC Framework Installation');
|
|
32
43
|
logger.dim(`Target: ${targetPath}`);
|
|
@@ -62,12 +73,14 @@ export async function initCommand(options) {
|
|
|
62
73
|
|
|
63
74
|
// 2. Create .morph directory structure
|
|
64
75
|
spinner.text = 'Creating .morph structure...';
|
|
65
|
-
const projectPath = join(morphPath, 'project');
|
|
66
76
|
const configDir = join(morphPath, 'config');
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
const frameworkDestDir = join(morphPath, 'framework');
|
|
78
|
+
const contextDir = join(morphPath, 'context');
|
|
79
|
+
const featuresDir = join(morphPath, 'features');
|
|
80
|
+
await ensureDir(contextDir);
|
|
81
|
+
await ensureDir(featuresDir);
|
|
70
82
|
await ensureDir(configDir);
|
|
83
|
+
await ensureDir(frameworkDestDir);
|
|
71
84
|
|
|
72
85
|
// 3. Create config.json
|
|
73
86
|
spinner.text = 'Generating config.json...';
|
|
@@ -87,7 +100,7 @@ export async function initCommand(options) {
|
|
|
87
100
|
|
|
88
101
|
// 4. Create context/README.md
|
|
89
102
|
spinner.text = 'Creating context README...';
|
|
90
|
-
const contextReadme = join(
|
|
103
|
+
const contextReadme = join(contextDir, 'README.md');
|
|
91
104
|
const readmeContent = `# ${dirName} - Project Context
|
|
92
105
|
|
|
93
106
|
## Overview
|
|
@@ -111,7 +124,7 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
111
124
|
// 5. Copy framework templates (project-local overrides start from framework defaults)
|
|
112
125
|
const contentDir = getContentDir();
|
|
113
126
|
const frameworkTemplatesSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'templates');
|
|
114
|
-
const templatesDest = join(
|
|
127
|
+
const templatesDest = join(frameworkDestDir, 'templates');
|
|
115
128
|
let templatesCopied = false;
|
|
116
129
|
if (await pathExists(frameworkTemplatesSrc)) {
|
|
117
130
|
await copyDirectory(frameworkTemplatesSrc, templatesDest);
|
|
@@ -123,7 +136,7 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
123
136
|
// 6b. Copy framework standards hierarchy (universal standards)
|
|
124
137
|
spinner.text = 'Copying framework standards hierarchy...';
|
|
125
138
|
const frameworkStandardsSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'standards');
|
|
126
|
-
const frameworkStandardsDest = join(
|
|
139
|
+
const frameworkStandardsDest = join(frameworkDestDir, 'standards');
|
|
127
140
|
if (await pathExists(frameworkStandardsSrc)) {
|
|
128
141
|
// Copy entire hierarchy (core/, backend/, frontend/, infrastructure/)
|
|
129
142
|
await copyDirectory(frameworkStandardsSrc, frameworkStandardsDest);
|
|
@@ -133,25 +146,12 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
133
146
|
// 7. Copy agents.json (sourced from framework/ — canonical single source of truth)
|
|
134
147
|
spinner.text = 'Copying agents configuration...';
|
|
135
148
|
const agentsSrc = join(import.meta.dirname, '..', '..', '..', 'framework', 'agents.json');
|
|
136
|
-
const agentsDest = join(
|
|
149
|
+
const agentsDest = join(frameworkDestDir, 'agents.json');
|
|
137
150
|
if (await pathExists(agentsSrc)) {
|
|
138
151
|
await copyFile(agentsSrc, agentsDest);
|
|
139
152
|
}
|
|
140
153
|
|
|
141
|
-
// 8. Copy
|
|
142
|
-
spinner.text = 'Copying Azure pricing data...';
|
|
143
|
-
const pricingSrc = join(contentDir, '.morph', 'config', 'azure-pricing.json');
|
|
144
|
-
const pricingDest = join(configDir, 'azure-pricing.json');
|
|
145
|
-
if (await pathExists(pricingSrc)) {
|
|
146
|
-
await copyFile(pricingSrc, pricingDest);
|
|
147
|
-
}
|
|
148
|
-
const pricingSchemaSrc = join(contentDir, '.morph', 'config', 'azure-pricing.schema.json');
|
|
149
|
-
const pricingSchemaDest = join(configDir, 'azure-pricing.schema.json');
|
|
150
|
-
if (await pathExists(pricingSchemaSrc)) {
|
|
151
|
-
await copyFile(pricingSchemaSrc, pricingSchemaDest);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 9. Copy .claude commands and create symlinks for skills
|
|
154
|
+
// 8. Copy .claude commands and create symlinks for skills
|
|
155
155
|
// Source: framework/ (canonical for all stacks)
|
|
156
156
|
spinner.text = 'Setting up Claude Code integration...';
|
|
157
157
|
const frameworkDir = join(import.meta.dirname, '..', '..', '..', 'framework');
|
|
@@ -220,9 +220,48 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
//
|
|
223
|
+
// 9a. Install path-scoped rules to .claude/rules/ (native Claude Code pattern)
|
|
224
|
+
spinner.text = 'Installing path-scoped rules to .claude/rules/...';
|
|
225
|
+
const rulesSrc = join(frameworkDir, 'rules');
|
|
226
|
+
const rulesDest = join(claudeDest, 'rules');
|
|
227
|
+
let rulesCopied = false;
|
|
228
|
+
if (await pathExists(rulesSrc)) {
|
|
229
|
+
await copyDirectory(rulesSrc, rulesDest);
|
|
230
|
+
rulesCopied = true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 9b. Install morph skills to .claude/skills/ for native Claude Code discovery
|
|
234
|
+
spinner.text = 'Installing morph skills to .claude/skills/...';
|
|
235
|
+
await installSkills(targetPath);
|
|
236
|
+
|
|
237
|
+
// 9b2. Install tier-1/2 agents as native Claude Code subagents in .claude/agents/
|
|
238
|
+
spinner.text = 'Installing native subagents to .claude/agents/...';
|
|
239
|
+
await installAgents(targetPath, frameworkDir);
|
|
240
|
+
|
|
241
|
+
// 9b2b. Install level-2 domain agents as native Claude Code subagents in .claude/agents/
|
|
242
|
+
await installDomainAgents(targetPath, frameworkDir);
|
|
243
|
+
|
|
244
|
+
// 9b3. Install runtime CLAUDE.md to .claude/CLAUDE.md (Claude Code runtime instructions)
|
|
245
|
+
spinner.text = 'Installing .claude/CLAUDE.md...';
|
|
246
|
+
const runtimeClaudeMdSrc = join(frameworkDir, 'CLAUDE.md');
|
|
247
|
+
const runtimeClaudeMdDest = join(claudeDest, 'CLAUDE.md');
|
|
248
|
+
if (await pathExists(runtimeClaudeMdSrc)) {
|
|
249
|
+
await copyFile(runtimeClaudeMdSrc, runtimeClaudeMdDest);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 9c. Install statusline globally to ~/.claude/ (applies to all Claude Code sessions)
|
|
253
|
+
spinner.text = 'Installing statusline globally to ~/.claude/...';
|
|
254
|
+
const HOOKS_SRC = join(import.meta.dirname, '..', '..', '..', 'framework', 'hooks', 'claude-code');
|
|
255
|
+
try {
|
|
256
|
+
await installGlobalStatusline(HOOKS_SRC);
|
|
257
|
+
} catch {
|
|
258
|
+
// Non-critical: global dir may not be writable in all environments
|
|
259
|
+
logger.dim(' ⚠ Could not install statusline globally (non-critical)');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 9d. Install/update Claude Code hooks in .claude/settings.local.json
|
|
224
263
|
spinner.text = 'Installing Claude Code hooks...';
|
|
225
|
-
const
|
|
264
|
+
const hooksResult = await installClaudeHooks(targetPath);
|
|
226
265
|
|
|
227
266
|
// 10. Save version info
|
|
228
267
|
spinner.text = 'Saving version info...';
|
|
@@ -233,6 +272,234 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
233
272
|
spinner.text = 'Updating .gitignore...';
|
|
234
273
|
await updateGitignore(targetPath);
|
|
235
274
|
|
|
275
|
+
// 11b. Detect Claude Code environment (plugins, MCPs, skills)
|
|
276
|
+
spinner.text = 'Detecting Claude Code environment...';
|
|
277
|
+
let claudeConfigDetected = null;
|
|
278
|
+
let integrationsCreated = false;
|
|
279
|
+
try {
|
|
280
|
+
claudeConfigDetected = await detectClaudeConfig(targetPath);
|
|
281
|
+
const hasIntegrations = claudeConfigDetected.plugins.length > 0
|
|
282
|
+
|| claudeConfigDetected.mcpServers.length > 0
|
|
283
|
+
|| claudeConfigDetected.superpowers.installed;
|
|
284
|
+
|
|
285
|
+
if (hasIntegrations) {
|
|
286
|
+
spinner.stop();
|
|
287
|
+
logger.blank();
|
|
288
|
+
logger.header('Claude Code Environment Detected');
|
|
289
|
+
|
|
290
|
+
const summary = formatConfigSummary(claudeConfigDetected);
|
|
291
|
+
if (summary) {
|
|
292
|
+
logger.info(summary);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Show MCP-to-phase mapping
|
|
296
|
+
if (claudeConfigDetected.mcpServers.length > 0) {
|
|
297
|
+
const phaseMap = mapMcpsToPhases(claudeConfigDetected.mcpServers);
|
|
298
|
+
logger.blank();
|
|
299
|
+
logger.dim('MCP usage by phase:');
|
|
300
|
+
for (const [phase, mcps] of Object.entries(phaseMap)) {
|
|
301
|
+
if (mcps.length > 0) {
|
|
302
|
+
logger.dim(` ${phase}: ${mcps.map(m => m.name).join(', ')}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
logger.blank();
|
|
308
|
+
const { saveIntegrationsChoice } = await inquirer.prompt([{
|
|
309
|
+
type: 'confirm',
|
|
310
|
+
name: 'saveIntegrationsChoice',
|
|
311
|
+
message: 'Save detected integrations and generate optimized settings?',
|
|
312
|
+
default: true
|
|
313
|
+
}]);
|
|
314
|
+
|
|
315
|
+
if (saveIntegrationsChoice) {
|
|
316
|
+
spinner.start('Saving integrations...');
|
|
317
|
+
await saveIntegrations(targetPath, claudeConfigDetected);
|
|
318
|
+
await generateSettings(targetPath, claudeConfigDetected, config);
|
|
319
|
+
integrationsCreated = true;
|
|
320
|
+
spinner.succeed('Integrations saved to .morph/config/integrations.json');
|
|
321
|
+
} else {
|
|
322
|
+
spinner.start('Continuing...');
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
} catch (error) {
|
|
326
|
+
// Non-fatal: continue without integrations
|
|
327
|
+
logger.dim(` Claude config detection skipped: ${error.message}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// 11c. Stack detection (moved before MCP setup so we know the stack)
|
|
331
|
+
spinner.text = 'Detecting project stack...';
|
|
332
|
+
let detectedStack = 'unknown';
|
|
333
|
+
const hasProjectFiles = await pathExists(join(targetPath, 'package.json'))
|
|
334
|
+
|| await pathExists(join(targetPath, 'src'))
|
|
335
|
+
|| (await fs.readdir(targetPath)).some(f => f.endsWith('.csproj'));
|
|
336
|
+
|
|
337
|
+
if (hasProjectFiles) {
|
|
338
|
+
try {
|
|
339
|
+
const quickResults = await detectProject(targetPath, { conversation: false, generateStandards: false });
|
|
340
|
+
const structure = quickResults.structure;
|
|
341
|
+
|
|
342
|
+
if (structure?.stack && structure.stack !== 'unknown') {
|
|
343
|
+
detectedStack = structure.stack;
|
|
344
|
+
spinner.stop();
|
|
345
|
+
logger.blank();
|
|
346
|
+
logger.header('Existing Project Detected');
|
|
347
|
+
logger.info(`Stack detected: ${structure.stack}`);
|
|
348
|
+
if (structure?.architecture) logger.dim(`Architecture: ${structure.architecture}`);
|
|
349
|
+
if (structure?.uiLibrary) logger.dim(`UI Library: ${structure.uiLibrary}`);
|
|
350
|
+
|
|
351
|
+
const { standardsChoice } = await inquirer.prompt([{
|
|
352
|
+
type: 'list',
|
|
353
|
+
name: 'standardsChoice',
|
|
354
|
+
message: 'How should morph-spec handle your project standards?',
|
|
355
|
+
choices: [
|
|
356
|
+
{ name: 'Keep morph-spec defaults (recommended)', value: 'morph-spec' },
|
|
357
|
+
{ name: 'Detect project-specific standards', value: 'detect' }
|
|
358
|
+
]
|
|
359
|
+
}]);
|
|
360
|
+
|
|
361
|
+
if (standardsChoice === 'detect') {
|
|
362
|
+
spinner.start('Generating project-specific standards...');
|
|
363
|
+
const fullResults = await detectProject(targetPath, { conversation: false });
|
|
364
|
+
const inferredPath = join(contextDir, 'standards.md');
|
|
365
|
+
await writeFile(inferredPath, fullResults.inferred.markdown);
|
|
366
|
+
spinner.succeed('Generated .morph/context/standards.md');
|
|
367
|
+
logger.dim('Review and edit .morph/context/standards.md as needed.');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
spinner.start('Continuing...');
|
|
371
|
+
}
|
|
372
|
+
} catch (error) {
|
|
373
|
+
logger.dim(` Stack detection skipped: ${error.message}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 11d. MCP Auto-Setup
|
|
378
|
+
let mcpSetupResult = null;
|
|
379
|
+
if (!options.skipMcp) {
|
|
380
|
+
try {
|
|
381
|
+
spinner.stop();
|
|
382
|
+
const existingMcps = claudeConfigDetected?.mcpServers || [];
|
|
383
|
+
const orchestration = orchestrateMcpSetup(targetPath, detectedStack, existingMcps);
|
|
384
|
+
|
|
385
|
+
const autoNames = Object.keys(orchestration.autoInstallable);
|
|
386
|
+
const manualNames = Object.keys(orchestration.needsManualSetup);
|
|
387
|
+
const hasAutoMcps = autoNames.length > 0;
|
|
388
|
+
const hasManualMcps = manualNames.length > 0;
|
|
389
|
+
|
|
390
|
+
if (hasAutoMcps || hasManualMcps) {
|
|
391
|
+
logger.blank();
|
|
392
|
+
logger.header('MCP Server Setup');
|
|
393
|
+
|
|
394
|
+
// Auto-install prompt
|
|
395
|
+
let autoInstalled = {};
|
|
396
|
+
if (hasAutoMcps) {
|
|
397
|
+
const { installAuto } = await inquirer.prompt([{
|
|
398
|
+
type: 'confirm',
|
|
399
|
+
name: 'installAuto',
|
|
400
|
+
message: `Install recommended MCP servers? (${autoNames.join(', ')})`,
|
|
401
|
+
default: true
|
|
402
|
+
}]);
|
|
403
|
+
|
|
404
|
+
if (installAuto) {
|
|
405
|
+
spinner.start('Installing MCP servers...');
|
|
406
|
+
const result = await installAutoMcps(targetPath, orchestration.autoInstallable);
|
|
407
|
+
spinner.succeed(`Installed ${result.added.length} MCP server(s)`);
|
|
408
|
+
for (const name of result.added) {
|
|
409
|
+
autoInstalled[name] = orchestration.autoInstallable[name];
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Credential MCPs — inline setup or instructions
|
|
415
|
+
const manualInstalled = {};
|
|
416
|
+
if (hasManualMcps) {
|
|
417
|
+
for (const [name, entry] of Object.entries(orchestration.needsManualSetup)) {
|
|
418
|
+
logger.blank();
|
|
419
|
+
|
|
420
|
+
// Show warnings
|
|
421
|
+
for (const warning of entry.install.warnings || []) {
|
|
422
|
+
logger.warn(` ${warning}`);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
426
|
+
const { setupNow } = await inquirer.prompt([{
|
|
427
|
+
type: 'confirm',
|
|
428
|
+
name: 'setupNow',
|
|
429
|
+
message: `Set up ${capitalizedName} MCP now? (${entry.usage})`,
|
|
430
|
+
default: false
|
|
431
|
+
}]);
|
|
432
|
+
|
|
433
|
+
if (setupNow) {
|
|
434
|
+
// Collect credentials
|
|
435
|
+
const credentialValues = {};
|
|
436
|
+
for (const cred of entry.install.credentials) {
|
|
437
|
+
const { value } = await inquirer.prompt([{
|
|
438
|
+
type: cred.secret ? 'password' : 'input',
|
|
439
|
+
name: 'value',
|
|
440
|
+
message: `${cred.name}:`,
|
|
441
|
+
mask: cred.secret ? '*' : undefined
|
|
442
|
+
}]);
|
|
443
|
+
credentialValues[cred.envVar] = value;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
spinner.start(`Configuring ${name}...`);
|
|
447
|
+
await installMcpWithCredentials(targetPath, name, entry, credentialValues);
|
|
448
|
+
spinner.succeed(`${capitalizedName} MCP configured`);
|
|
449
|
+
manualInstalled[name] = entry;
|
|
450
|
+
} else {
|
|
451
|
+
// Show setup instructions
|
|
452
|
+
const instructions = generateSetupInstructions(name, entry);
|
|
453
|
+
logger.blank();
|
|
454
|
+
logger.dim(' Add to .claude/settings.local.json → mcpServers:');
|
|
455
|
+
logger.dim(' ' + '─'.repeat(55));
|
|
456
|
+
for (const line of instructions.configSnippet.split('\n')) {
|
|
457
|
+
logger.dim(` ${line}`);
|
|
458
|
+
}
|
|
459
|
+
logger.dim(' ' + '─'.repeat(55));
|
|
460
|
+
|
|
461
|
+
for (const cred of instructions.credentialUrls) {
|
|
462
|
+
logger.dim(` Get ${cred.name}: ${cred.helpUrl}`);
|
|
463
|
+
}
|
|
464
|
+
logger.dim(` Or run later: ${instructions.cliCommand}`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Summary table
|
|
470
|
+
const justInstalled = { ...autoInstalled, ...manualInstalled };
|
|
471
|
+
const statusRows = formatMcpStatusTable(orchestration, justInstalled);
|
|
472
|
+
|
|
473
|
+
if (statusRows.length > 0) {
|
|
474
|
+
logger.blank();
|
|
475
|
+
logger.info('MCP Servers');
|
|
476
|
+
logger.dim('─'.repeat(60));
|
|
477
|
+
|
|
478
|
+
const STATUS_ICONS = {
|
|
479
|
+
installed: '✓',
|
|
480
|
+
available: '○',
|
|
481
|
+
already_configured: '✓',
|
|
482
|
+
needs_setup: '⚠',
|
|
483
|
+
prereq_missing: '✗',
|
|
484
|
+
not_relevant: '─'
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
for (const row of statusRows) {
|
|
488
|
+
const icon = STATUS_ICONS[row.status] || '?';
|
|
489
|
+
const statusLabel = row.status.replace(/_/g, ' ');
|
|
490
|
+
logger.dim(` ${icon} ${row.name.padEnd(15)} ${statusLabel.padEnd(20)} ${row.detail}`);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
mcpSetupResult = { autoInstalled, manualInstalled, orchestration };
|
|
495
|
+
}
|
|
496
|
+
} catch (error) {
|
|
497
|
+
logger.dim(` MCP setup skipped: ${error.message}`);
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
logger.dim('\nSkipped MCP setup (--skip-mcp flag)');
|
|
501
|
+
}
|
|
502
|
+
|
|
236
503
|
spinner.succeed('MORPH-SPEC installed successfully!');
|
|
237
504
|
|
|
238
505
|
// Show next steps
|
|
@@ -242,7 +509,7 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
242
509
|
logger.header('Next Steps');
|
|
243
510
|
|
|
244
511
|
logger.step(1, 'Run detection: morph-spec detect');
|
|
245
|
-
logger.step(2, 'Review .morph/config.json and .morph/
|
|
512
|
+
logger.step(2, 'Review .morph/config/config.json and .morph/context/standards.md');
|
|
246
513
|
logger.step(3, 'Open project in VS Code with Claude Code');
|
|
247
514
|
logger.step(4, 'Start your first feature:');
|
|
248
515
|
logger.blank();
|
|
@@ -253,16 +520,27 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
253
520
|
|
|
254
521
|
logger.info('Files installed:');
|
|
255
522
|
logger.dim(` ✓ CLAUDE.md`);
|
|
256
|
-
logger.dim(` ✓ .morph/config/ (config.json
|
|
257
|
-
logger.dim(` ✓ .morph/
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
logger.dim(` ✓ .morph/project/ (context, standards, outputs)`);
|
|
523
|
+
logger.dim(` ✓ .morph/config/ (config.json)`);
|
|
524
|
+
logger.dim(` ✓ .morph/framework/ (agents.json, standards/, templates/)`);
|
|
525
|
+
logger.dim(` ✓ .morph/context/ (project context)`);
|
|
526
|
+
logger.dim(` ✓ .morph/features/ (feature outputs)`);
|
|
262
527
|
if (commandsCopied) {
|
|
263
528
|
logger.dim(` ✓ .claude/commands/ (slash commands)`);
|
|
264
529
|
}
|
|
265
|
-
|
|
530
|
+
if (rulesCopied) {
|
|
531
|
+
logger.dim(` ✓ .claude/rules/ (5 path-scoped rules)`);
|
|
532
|
+
}
|
|
533
|
+
logger.dim(` ✓ .claude/settings.local.json (${hooksResult.installed} hooks installed)`);
|
|
534
|
+
if (integrationsCreated) {
|
|
535
|
+
logger.dim(` ✓ .morph/config/integrations.json (detected plugins & MCPs)`);
|
|
536
|
+
}
|
|
537
|
+
if (mcpSetupResult) {
|
|
538
|
+
const autoCount = Object.keys(mcpSetupResult.autoInstalled).length;
|
|
539
|
+
const manualCount = Object.keys(mcpSetupResult.manualInstalled).length;
|
|
540
|
+
if (autoCount + manualCount > 0) {
|
|
541
|
+
logger.dim(` ✓ MCP servers (${autoCount + manualCount} configured)`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
266
544
|
|
|
267
545
|
if (symlinkCount > 0) {
|
|
268
546
|
const linkType = process.platform === 'win32' ? 'junction-linked' : 'symlinked';
|
|
@@ -274,48 +552,6 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
274
552
|
|
|
275
553
|
logger.blank();
|
|
276
554
|
|
|
277
|
-
// 12. Interactive stack/standards detection for existing projects
|
|
278
|
-
const hasProjectFiles = await pathExists(join(targetPath, 'package.json'))
|
|
279
|
-
|| await pathExists(join(targetPath, 'src'))
|
|
280
|
-
|| (await fs.readdir(targetPath)).some(f => f.endsWith('.csproj'));
|
|
281
|
-
|
|
282
|
-
if (hasProjectFiles) {
|
|
283
|
-
logger.blank();
|
|
284
|
-
logger.header('Existing Project Detected');
|
|
285
|
-
|
|
286
|
-
try {
|
|
287
|
-
const quickResults = await detectProject(targetPath, { conversation: false, generateStandards: false });
|
|
288
|
-
const structure = quickResults.structure;
|
|
289
|
-
|
|
290
|
-
if (structure?.stack && structure.stack !== 'unknown') {
|
|
291
|
-
logger.info(`Stack detected: ${structure.stack}`);
|
|
292
|
-
if (structure?.architecture) logger.dim(`Architecture: ${structure.architecture}`);
|
|
293
|
-
if (structure?.uiLibrary) logger.dim(`UI Library: ${structure.uiLibrary}`);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const { standardsChoice } = await inquirer.prompt([{
|
|
297
|
-
type: 'list',
|
|
298
|
-
name: 'standardsChoice',
|
|
299
|
-
message: 'How should morph-spec handle your project standards?',
|
|
300
|
-
choices: [
|
|
301
|
-
{ name: 'Keep morph-spec defaults (recommended)', value: 'morph-spec' },
|
|
302
|
-
{ name: 'Detect project-specific standards', value: 'detect' }
|
|
303
|
-
]
|
|
304
|
-
}]);
|
|
305
|
-
|
|
306
|
-
if (standardsChoice === 'detect') {
|
|
307
|
-
spinner.start('Generating project-specific standards...');
|
|
308
|
-
const fullResults = await detectProject(targetPath, { conversation: false });
|
|
309
|
-
const inferredPath = join(morphPath, 'project', 'standards', 'inferred.md');
|
|
310
|
-
await writeFile(inferredPath, fullResults.inferred.markdown);
|
|
311
|
-
spinner.succeed('Generated .morph/project/standards/inferred.md');
|
|
312
|
-
logger.dim('Review and edit .morph/project/standards/inferred.md as needed.');
|
|
313
|
-
}
|
|
314
|
-
} catch (error) {
|
|
315
|
-
logger.warn(`Stack detection failed: ${error.message}`);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
555
|
// 13. LLM-based auto-detect project context (if Claude Code is available and not --skip-detection)
|
|
320
556
|
if (!options.skipDetection && detectClaudeCode()) {
|
|
321
557
|
logger.blank();
|
|
@@ -349,6 +585,12 @@ Run \`morph-spec detect\` to analyze your project.
|
|
|
349
585
|
logger.dim('Run "morph-spec update --wizard" to configure manually.');
|
|
350
586
|
}
|
|
351
587
|
|
|
588
|
+
// Suggest tutorial for first-time users
|
|
589
|
+
if (integrationsCreated) {
|
|
590
|
+
logger.blank();
|
|
591
|
+
logger.info('First time using morph-spec? Run `morph-spec tutorial` to get started.');
|
|
592
|
+
}
|
|
593
|
+
|
|
352
594
|
logger.blank();
|
|
353
595
|
|
|
354
596
|
} catch (error) {
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MORPH-SPEC Revert Command
|
|
3
|
+
*
|
|
4
|
+
* Revert a feature to a previous phase, optionally deleting later-phase outputs.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* morph-spec revert <feature-name> --to <phase>
|
|
8
|
+
* morph-spec revert <feature-name> --to design
|
|
9
|
+
* morph-spec revert <feature-name> --to design --delete-outputs
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import chalk from 'chalk';
|
|
15
|
+
import { loadState, saveState, getFeature } from '../../core/state/state-manager.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Phase order for revert logic
|
|
19
|
+
*/
|
|
20
|
+
const PHASE_ORDER = [
|
|
21
|
+
{ key: 'proposal', order: 0, outputs: ['proposal.md'] },
|
|
22
|
+
{ key: 'setup', order: 1, outputs: [] },
|
|
23
|
+
{ key: 'uiux', order: 2, outputs: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'] },
|
|
24
|
+
{ key: 'design', order: 3, outputs: ['spec.md', 'schema-analysis.md', 'contracts.cs', 'decisions.md'] },
|
|
25
|
+
{ key: 'clarify', order: 4, outputs: ['clarifications.md'] },
|
|
26
|
+
{ key: 'tasks', order: 5, outputs: ['tasks.md', 'tasks.json'] },
|
|
27
|
+
{ key: 'implement', order: 6, outputs: ['recap.md'] },
|
|
28
|
+
{ key: 'sync', order: 7, outputs: [] }
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get outputs that would be affected by reverting to a phase
|
|
33
|
+
*/
|
|
34
|
+
function getAffectedOutputs(targetPhase) {
|
|
35
|
+
const targetOrder = PHASE_ORDER.find(p => p.key === targetPhase)?.order ?? -1;
|
|
36
|
+
const affected = [];
|
|
37
|
+
|
|
38
|
+
for (const phase of PHASE_ORDER) {
|
|
39
|
+
if (phase.order > targetOrder) {
|
|
40
|
+
affected.push(...phase.outputs.map(o => ({ phase: phase.key, file: o })));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return affected;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Main revert command
|
|
49
|
+
*/
|
|
50
|
+
export async function revertCommand(featureName, options = {}) {
|
|
51
|
+
if (!featureName) {
|
|
52
|
+
console.error(chalk.red('Error: Feature name required'));
|
|
53
|
+
console.error(chalk.gray('Usage: morph-spec revert <feature-name> --to <phase>'));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const targetPhase = options.to;
|
|
58
|
+
if (!targetPhase) {
|
|
59
|
+
console.error(chalk.red('Error: Target phase required (--to <phase>)'));
|
|
60
|
+
console.error(chalk.gray(`Valid phases: ${PHASE_ORDER.map(p => p.key).join(', ')}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const targetDef = PHASE_ORDER.find(p => p.key === targetPhase);
|
|
65
|
+
if (!targetDef) {
|
|
66
|
+
console.error(chalk.red(`Error: Unknown phase: ${targetPhase}`));
|
|
67
|
+
console.error(chalk.gray(`Valid phases: ${PHASE_ORDER.map(p => p.key).join(', ')}`));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const feature = getFeature(featureName);
|
|
72
|
+
if (!feature) {
|
|
73
|
+
console.error(chalk.red(`Error: Feature '${featureName}' not found`));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const currentDef = PHASE_ORDER.find(p => p.key === feature.phase);
|
|
78
|
+
if (currentDef && targetDef.order >= currentDef.order) {
|
|
79
|
+
console.error(chalk.red(`Error: Cannot revert forward. Current phase: ${feature.phase}, target: ${targetPhase}`));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Get affected outputs
|
|
84
|
+
const affected = getAffectedOutputs(targetPhase);
|
|
85
|
+
const outputDir = path.join(process.cwd(), '.morph/features', featureName);
|
|
86
|
+
const existingAffected = affected.filter(a =>
|
|
87
|
+
fs.existsSync(path.join(outputDir, a.file))
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Show what will happen
|
|
91
|
+
console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
|
|
92
|
+
console.log(chalk.cyan('│ MORPH-SPEC REVERT │'));
|
|
93
|
+
console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
|
|
94
|
+
|
|
95
|
+
console.log(chalk.white.bold(`Feature: ${featureName}`));
|
|
96
|
+
console.log(chalk.gray(`Current phase: ${feature.phase} → Reverting to: ${targetPhase}\n`));
|
|
97
|
+
|
|
98
|
+
if (existingAffected.length > 0) {
|
|
99
|
+
if (options.deleteOutputs) {
|
|
100
|
+
console.log(chalk.yellow('The following files will be DELETED:'));
|
|
101
|
+
} else {
|
|
102
|
+
console.log(chalk.yellow('The following outputs will be marked as draft (files preserved):'));
|
|
103
|
+
}
|
|
104
|
+
for (const item of existingAffected) {
|
|
105
|
+
console.log(chalk.gray(` - ${item.file} (from ${item.phase} phase)`));
|
|
106
|
+
}
|
|
107
|
+
console.log('');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Update state
|
|
111
|
+
const state = loadState();
|
|
112
|
+
const stateFeature = state.features[featureName];
|
|
113
|
+
|
|
114
|
+
// Revert phase
|
|
115
|
+
stateFeature.phase = targetPhase;
|
|
116
|
+
stateFeature.updatedAt = new Date().toISOString();
|
|
117
|
+
|
|
118
|
+
// Mark affected outputs as not created in state
|
|
119
|
+
const outputKeyMap = {
|
|
120
|
+
'proposal.md': 'proposal',
|
|
121
|
+
'spec.md': 'spec',
|
|
122
|
+
'schema-analysis.md': 'schemaAnalysis',
|
|
123
|
+
'contracts.cs': 'contracts',
|
|
124
|
+
'decisions.md': 'decisions',
|
|
125
|
+
'clarifications.md': 'clarifications',
|
|
126
|
+
'tasks.md': 'tasks',
|
|
127
|
+
'tasks.json': 'tasks',
|
|
128
|
+
'ui-design-system.md': 'uiDesignSystem',
|
|
129
|
+
'ui-mockups.md': 'uiMockups',
|
|
130
|
+
'ui-components.md': 'uiComponents',
|
|
131
|
+
'ui-flows.md': 'uiFlows',
|
|
132
|
+
'recap.md': 'recap'
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
for (const item of affected) {
|
|
136
|
+
const key = outputKeyMap[item.file];
|
|
137
|
+
if (key && stateFeature.outputs[key]) {
|
|
138
|
+
stateFeature.outputs[key].created = false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Reset approval gates for later phases
|
|
143
|
+
for (const phase of PHASE_ORDER) {
|
|
144
|
+
if (phase.order > targetDef.order && stateFeature.approvalGates?.[phase.key]) {
|
|
145
|
+
stateFeature.approvalGates[phase.key].approved = false;
|
|
146
|
+
stateFeature.approvalGates[phase.key].timestamp = null;
|
|
147
|
+
stateFeature.approvalGates[phase.key].approvedBy = null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Reset tasks if reverting before tasks phase
|
|
152
|
+
if (targetDef.order < 5) {
|
|
153
|
+
stateFeature.tasks = { total: 0, completed: 0, inProgress: 0, pending: 0 };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
saveState(state);
|
|
157
|
+
|
|
158
|
+
// Delete files if requested
|
|
159
|
+
if (options.deleteOutputs && existingAffected.length > 0) {
|
|
160
|
+
for (const item of existingAffected) {
|
|
161
|
+
const filePath = path.join(outputDir, item.file);
|
|
162
|
+
if (fs.existsSync(filePath)) {
|
|
163
|
+
fs.unlinkSync(filePath);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
console.log(chalk.yellow(`Deleted ${existingAffected.length} file(s).`));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(chalk.green(`✓ Feature '${featureName}' reverted to phase: ${targetPhase}`));
|
|
170
|
+
console.log(chalk.gray(` State updated. Run 'morph-spec status ${featureName}' to see current status.\n`));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export default revertCommand;
|