@polymorphism-tech/morph-spec 4.3.7 → 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 -1
- 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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standards CLI Commands
|
|
3
|
+
*
|
|
4
|
+
* Provides browsable access to the framework standards registry.
|
|
5
|
+
* Usage:
|
|
6
|
+
* morph-spec standards --list
|
|
7
|
+
* morph-spec standards --search <query>
|
|
8
|
+
* morph-spec standards --show <id>
|
|
9
|
+
* morph-spec standards --category <cat>
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync } from 'fs';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { logger } from '../../utils/logger.js';
|
|
16
|
+
|
|
17
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
18
|
+
const REGISTRY_PATH = join(__dirname, '..', '..', '..', 'framework', 'standards', 'STANDARDS.json');
|
|
19
|
+
|
|
20
|
+
function loadRegistry() {
|
|
21
|
+
return JSON.parse(readFileSync(REGISTRY_PATH, 'utf8')).standards;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* List all standards, optionally filtered by category.
|
|
26
|
+
* @param {{ json?: boolean, category?: string }} opts
|
|
27
|
+
* @returns {Promise<Array>}
|
|
28
|
+
*/
|
|
29
|
+
export async function listStandards({ json, category } = {}) {
|
|
30
|
+
let standards = loadRegistry();
|
|
31
|
+
if (category) {
|
|
32
|
+
standards = standards.filter(s => s.category === category);
|
|
33
|
+
}
|
|
34
|
+
if (json) return standards;
|
|
35
|
+
standards.forEach(s =>
|
|
36
|
+
logger.info(`${s.id.padEnd(55)} ${s.category}`)
|
|
37
|
+
);
|
|
38
|
+
return standards;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Search standards by query string (matches id, name, or tags).
|
|
43
|
+
* @param {string} query
|
|
44
|
+
* @param {{ json?: boolean }} opts
|
|
45
|
+
* @returns {Promise<Array>}
|
|
46
|
+
*/
|
|
47
|
+
export async function searchStandards(query, { json } = {}) {
|
|
48
|
+
const q = query.toLowerCase();
|
|
49
|
+
const results = loadRegistry().filter(s =>
|
|
50
|
+
s.name.toLowerCase().includes(q) ||
|
|
51
|
+
s.id.toLowerCase().includes(q) ||
|
|
52
|
+
s.tags.some(t => t.toLowerCase().includes(q))
|
|
53
|
+
);
|
|
54
|
+
if (json) return results;
|
|
55
|
+
if (results.length === 0) {
|
|
56
|
+
logger.warn(`No standards found matching "${query}"`);
|
|
57
|
+
} else {
|
|
58
|
+
results.forEach(s => logger.info(`${s.id}: ${s.name} [${s.category}]`));
|
|
59
|
+
}
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Show the full content of a standard by its id.
|
|
65
|
+
* @param {string} id
|
|
66
|
+
* @returns {Promise<string|null>}
|
|
67
|
+
*/
|
|
68
|
+
export async function showStandard(id) {
|
|
69
|
+
const standard = loadRegistry().find(s => s.id === id);
|
|
70
|
+
if (!standard) {
|
|
71
|
+
logger.error(`Standard '${id}' not found. Use --list to see available standards.`);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const content = readFileSync(
|
|
75
|
+
join(__dirname, '..', '..', '..', 'framework', 'standards', standard.path),
|
|
76
|
+
'utf8'
|
|
77
|
+
);
|
|
78
|
+
logger.info(content);
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MORPH-SPEC Feature Status Command
|
|
3
|
+
*
|
|
4
|
+
* Displays a comprehensive dashboard showing feature progress, phase status,
|
|
5
|
+
* outputs, tasks, approvals, and next steps.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* morph-spec status <feature-name>
|
|
9
|
+
* morph-spec status <feature-name> --json
|
|
10
|
+
*
|
|
11
|
+
* Example:
|
|
12
|
+
* morph-spec status user-portal
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
import { loadState, getFeature, derivePhase, deriveOutputs } from '../../core/state/state-manager.js';
|
|
17
|
+
import { PHASES } from '../state/validate-phase.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Phase symbols for visual representation
|
|
21
|
+
*/
|
|
22
|
+
const PHASE_SYMBOLS = {
|
|
23
|
+
completed: '✅',
|
|
24
|
+
current: '⏸️',
|
|
25
|
+
pending: '⬜',
|
|
26
|
+
skipped: '⊘'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Phase definitions with order
|
|
31
|
+
*/
|
|
32
|
+
const PHASE_ORDER = [
|
|
33
|
+
{ key: 'proposal', name: 'FASE 0: PROPOSAL', order: 0 },
|
|
34
|
+
{ key: 'setup', name: 'FASE 1: SETUP', order: 1 },
|
|
35
|
+
{ key: 'uiux', name: 'FASE 1.5: UI/UX', order: 2, optional: true },
|
|
36
|
+
{ key: 'design', name: 'FASE 2: DESIGN', order: 3 },
|
|
37
|
+
{ key: 'clarify', name: 'FASE 3: CLARIFY', order: 4 },
|
|
38
|
+
{ key: 'tasks', name: 'FASE 4: TASKS', order: 5 },
|
|
39
|
+
{ key: 'implement', name: 'FASE 5: IMPLEMENT', order: 6 },
|
|
40
|
+
{ key: 'sync', name: 'FASE 6: SYNC', order: 7, optional: true }
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Calculate phase status (completed, current, pending, skipped)
|
|
45
|
+
*/
|
|
46
|
+
function getPhaseStatus(phaseKey, currentPhase, feature) {
|
|
47
|
+
const phase = PHASE_ORDER.find(p => p.key === phaseKey);
|
|
48
|
+
const current = PHASE_ORDER.find(p => p.key === currentPhase);
|
|
49
|
+
|
|
50
|
+
if (!phase || !current) return 'pending';
|
|
51
|
+
|
|
52
|
+
// Check if phase was skipped (optional phases)
|
|
53
|
+
if (phase.optional && phase.order < current.order) {
|
|
54
|
+
// Check if any outputs were created for this phase
|
|
55
|
+
const hasOutputs = checkPhaseOutputs(phaseKey, feature);
|
|
56
|
+
if (!hasOutputs) return 'skipped';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (phase.order < current.order) return 'completed';
|
|
60
|
+
if (phase.order === current.order) return 'current';
|
|
61
|
+
return 'pending';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if phase has any outputs created
|
|
66
|
+
*/
|
|
67
|
+
function checkPhaseOutputs(phaseKey, feature) {
|
|
68
|
+
const phaseOutputMap = {
|
|
69
|
+
proposal: ['proposal'],
|
|
70
|
+
uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
|
|
71
|
+
design: ['spec', 'contracts', 'schemaAnalysis', 'decisions'],
|
|
72
|
+
clarify: ['clarifications'],
|
|
73
|
+
tasks: ['tasks']
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const outputs = phaseOutputMap[phaseKey] || [];
|
|
77
|
+
return outputs.some(output => feature.outputs[output]?.created);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Format phase display with symbol and status
|
|
82
|
+
*/
|
|
83
|
+
function formatPhase(phaseKey, currentPhase, feature, options = {}) {
|
|
84
|
+
const phase = PHASE_ORDER.find(p => p.key === phaseKey);
|
|
85
|
+
const status = getPhaseStatus(phaseKey, currentPhase, feature);
|
|
86
|
+
const symbol = PHASE_SYMBOLS[status];
|
|
87
|
+
|
|
88
|
+
let display = `${symbol} ${phase.name}`;
|
|
89
|
+
|
|
90
|
+
if (phase.optional) {
|
|
91
|
+
display += ` ${chalk.gray('(optional)')}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (status === 'current') {
|
|
95
|
+
display = chalk.cyan(display) + chalk.cyan(' ← CURRENT');
|
|
96
|
+
} else if (status === 'completed') {
|
|
97
|
+
display = chalk.green(display);
|
|
98
|
+
} else if (status === 'skipped') {
|
|
99
|
+
display = chalk.gray(display + ' (skipped)');
|
|
100
|
+
} else {
|
|
101
|
+
display = chalk.gray(display);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add output files if verbose
|
|
105
|
+
if (options.verbose && status !== 'pending' && status !== 'skipped') {
|
|
106
|
+
const phaseOutputMap = {
|
|
107
|
+
proposal: ['proposal'],
|
|
108
|
+
uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
|
|
109
|
+
design: ['spec', 'contracts', 'schemaAnalysis', 'decisions'],
|
|
110
|
+
clarify: ['clarifications'],
|
|
111
|
+
tasks: ['tasks'],
|
|
112
|
+
implement: ['recap']
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const outputs = phaseOutputMap[phaseKey] || [];
|
|
116
|
+
const created = outputs.filter(o => feature.outputs[o]?.created);
|
|
117
|
+
if (created.length > 0) {
|
|
118
|
+
display += chalk.gray(`\n Files: ${created.length}/${outputs.length}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return display;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Calculate completion percentage
|
|
127
|
+
*/
|
|
128
|
+
function calculateCompletionPercentage(feature) {
|
|
129
|
+
const totalPhases = PHASE_ORDER.filter(p => !p.optional).length; // 6 required phases
|
|
130
|
+
const completedPhases = PHASE_ORDER.filter(p => {
|
|
131
|
+
if (p.optional) return false;
|
|
132
|
+
const status = getPhaseStatus(p.key, feature.phase, feature);
|
|
133
|
+
return status === 'completed';
|
|
134
|
+
}).length;
|
|
135
|
+
|
|
136
|
+
return Math.round((completedPhases / totalPhases) * 100);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get next steps based on current phase
|
|
141
|
+
*/
|
|
142
|
+
function getNextSteps(feature) {
|
|
143
|
+
const steps = [];
|
|
144
|
+
|
|
145
|
+
// Check for pending approvals relevant to current phase
|
|
146
|
+
const phaseApprovalMap = {
|
|
147
|
+
proposal: 'proposal',
|
|
148
|
+
setup: 'proposal',
|
|
149
|
+
uiux: 'uiux',
|
|
150
|
+
design: 'design',
|
|
151
|
+
clarify: 'design',
|
|
152
|
+
tasks: 'tasks',
|
|
153
|
+
implement: 'tasks'
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const relevantGate = phaseApprovalMap[feature.phase];
|
|
157
|
+
const approvalGates = feature.approvalGates || {};
|
|
158
|
+
|
|
159
|
+
if (relevantGate && approvalGates[relevantGate] && !approvalGates[relevantGate].approved) {
|
|
160
|
+
steps.push({
|
|
161
|
+
type: 'approval',
|
|
162
|
+
message: `Approve ${relevantGate} to advance`,
|
|
163
|
+
command: `morph-spec approve ${feature.name || 'feature'} ${relevantGate}`
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Check for missing outputs in current phase
|
|
168
|
+
const phaseOutputMap = {
|
|
169
|
+
proposal: ['proposal'],
|
|
170
|
+
design: ['spec', 'contracts'],
|
|
171
|
+
clarify: ['clarifications'],
|
|
172
|
+
tasks: ['tasks'],
|
|
173
|
+
implement: ['recap']
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const requiredOutputs = phaseOutputMap[feature.phase] || [];
|
|
177
|
+
const missingOutputs = requiredOutputs.filter(o => !feature.outputs[o]?.created);
|
|
178
|
+
|
|
179
|
+
if (missingOutputs.length > 0) {
|
|
180
|
+
steps.push({
|
|
181
|
+
type: 'output',
|
|
182
|
+
message: `Create missing outputs: ${missingOutputs.join(', ')}`,
|
|
183
|
+
command: null
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Suggest next phase if current is complete
|
|
188
|
+
const hasApprovalPending = relevantGate && approvalGates[relevantGate] && !approvalGates[relevantGate].approved;
|
|
189
|
+
if (missingOutputs.length === 0 && !hasApprovalPending) {
|
|
190
|
+
const currentPhaseIndex = PHASE_ORDER.findIndex(p => p.key === feature.phase);
|
|
191
|
+
if (currentPhaseIndex >= 0 && currentPhaseIndex < PHASE_ORDER.length - 1) {
|
|
192
|
+
const nextPhase = PHASE_ORDER[currentPhaseIndex + 1];
|
|
193
|
+
steps.push({
|
|
194
|
+
type: 'advance',
|
|
195
|
+
message: `Advance to ${nextPhase.name}`,
|
|
196
|
+
command: `morph-spec phase advance ${feature.name || 'feature'}`
|
|
197
|
+
});
|
|
198
|
+
} else if (currentPhaseIndex === PHASE_ORDER.length - 1) {
|
|
199
|
+
steps.push({
|
|
200
|
+
type: 'complete',
|
|
201
|
+
message: 'Feature complete! Consider archiving.',
|
|
202
|
+
command: null
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return steps;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Estimate remaining time based on tasks
|
|
212
|
+
*/
|
|
213
|
+
function estimateRemainingTime(feature) {
|
|
214
|
+
if (!feature.tasks || feature.tasks.total === 0) {
|
|
215
|
+
return 'Not estimated';
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const remaining = feature.tasks.total - feature.tasks.completed;
|
|
219
|
+
const avgHoursPerTask = 2; // Configurable estimate
|
|
220
|
+
const hours = remaining * avgHoursPerTask;
|
|
221
|
+
|
|
222
|
+
if (hours < 1) return '< 1 hour';
|
|
223
|
+
if (hours === 1) return '1 hour';
|
|
224
|
+
if (hours < 8) return `${hours} hours`;
|
|
225
|
+
const days = Math.ceil(hours / 8);
|
|
226
|
+
return `~${days} day${days > 1 ? 's' : ''} (${hours}h)`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Main status command
|
|
231
|
+
*/
|
|
232
|
+
export async function statusCommand(featureName, options = {}) {
|
|
233
|
+
if (!featureName) {
|
|
234
|
+
console.error(chalk.red('✗ Error: Feature name required'));
|
|
235
|
+
console.error(chalk.gray('Usage: morph-spec status <feature-name>'));
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const feature = getFeature(featureName);
|
|
240
|
+
if (!feature) {
|
|
241
|
+
console.error(chalk.red(`✗ Error: Feature '${featureName}' not found`));
|
|
242
|
+
console.error(chalk.gray(`Run 'morph-spec state get ${featureName}' to check if feature exists`));
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Derive phase and outputs from filesystem if not stored in state (v5.0.0+)
|
|
247
|
+
const { join } = await import('path');
|
|
248
|
+
const featurePath = join(process.cwd(), '.morph', 'features', featureName);
|
|
249
|
+
if (!feature.phase) {
|
|
250
|
+
feature.phase = derivePhase(featurePath);
|
|
251
|
+
}
|
|
252
|
+
if (!feature.outputs) {
|
|
253
|
+
feature.outputs = deriveOutputs(featureName, process.cwd());
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// JSON output mode
|
|
257
|
+
if (options.json) {
|
|
258
|
+
const status = {
|
|
259
|
+
feature: featureName,
|
|
260
|
+
phase: feature.phase,
|
|
261
|
+
status: feature.status,
|
|
262
|
+
workflow: feature.workflow,
|
|
263
|
+
completion: calculateCompletionPercentage(feature),
|
|
264
|
+
phases: PHASE_ORDER.map(p => ({
|
|
265
|
+
key: p.key,
|
|
266
|
+
name: p.name,
|
|
267
|
+
status: getPhaseStatus(p.key, feature.phase, feature),
|
|
268
|
+
optional: p.optional || false
|
|
269
|
+
})),
|
|
270
|
+
outputs: Object.entries(feature.outputs).map(([key, output]) => ({
|
|
271
|
+
type: key,
|
|
272
|
+
created: output.created,
|
|
273
|
+
path: output.path
|
|
274
|
+
})),
|
|
275
|
+
tasks: feature.tasks || { total: 0, completed: 0, inProgress: 0, pending: 0 },
|
|
276
|
+
approvals: feature.approvalGates || {},
|
|
277
|
+
nextSteps: getNextSteps(feature),
|
|
278
|
+
estimatedTimeRemaining: estimateRemainingTime(feature)
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
console.log(JSON.stringify(status, null, 2));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Visual dashboard output
|
|
286
|
+
console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
|
|
287
|
+
console.log(chalk.cyan('│ MORPH-SPEC STATUS │'));
|
|
288
|
+
console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
|
|
289
|
+
|
|
290
|
+
// Feature info
|
|
291
|
+
console.log(chalk.white.bold(`Feature: ${featureName}`));
|
|
292
|
+
console.log(chalk.gray(`Status: ${feature.status || 'unknown'}`));
|
|
293
|
+
console.log(chalk.gray(`Workflow: ${feature.workflow || 'auto'}`));
|
|
294
|
+
console.log(chalk.gray(`Completion: ${calculateCompletionPercentage(feature)}%`));
|
|
295
|
+
console.log('');
|
|
296
|
+
|
|
297
|
+
// Phase progression
|
|
298
|
+
console.log(chalk.white.bold('Phases:'));
|
|
299
|
+
console.log(chalk.cyan('├─────────────────────────────────────────────────────────────┤'));
|
|
300
|
+
PHASE_ORDER.forEach(phase => {
|
|
301
|
+
console.log(`│ ${formatPhase(phase.key, feature.phase, feature, options)}`);
|
|
302
|
+
});
|
|
303
|
+
console.log(chalk.cyan('└─────────────────────────────────────────────────────────────┘'));
|
|
304
|
+
console.log('');
|
|
305
|
+
|
|
306
|
+
// Outputs summary
|
|
307
|
+
const totalOutputs = Object.keys(feature.outputs).length;
|
|
308
|
+
const createdOutputs = Object.values(feature.outputs).filter(o => o.created).length;
|
|
309
|
+
console.log(chalk.white.bold(`Outputs: ${createdOutputs}/${totalOutputs} complete`));
|
|
310
|
+
|
|
311
|
+
if (options.verbose) {
|
|
312
|
+
console.log(chalk.gray('Output files:'));
|
|
313
|
+
Object.entries(feature.outputs).forEach(([key, output]) => {
|
|
314
|
+
const symbol = output.created ? '✅' : '⬜';
|
|
315
|
+
const display = output.created ? chalk.green(key) : chalk.gray(key);
|
|
316
|
+
console.log(` ${symbol} ${display}`);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
console.log('');
|
|
320
|
+
|
|
321
|
+
// Tasks progress
|
|
322
|
+
if (feature.tasks && feature.tasks.total > 0) {
|
|
323
|
+
console.log(chalk.white.bold('Tasks Progress:'));
|
|
324
|
+
const { total, completed, inProgress, pending } = feature.tasks;
|
|
325
|
+
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
326
|
+
|
|
327
|
+
console.log(` Total: ${total}`);
|
|
328
|
+
console.log(chalk.green(` ✓ Completed: ${completed} (${percentage}%)`));
|
|
329
|
+
if (inProgress > 0) console.log(chalk.cyan(` ▶ In Progress: ${inProgress}`));
|
|
330
|
+
if (pending > 0) console.log(chalk.gray(` ⬜ Pending: ${pending}`));
|
|
331
|
+
console.log(` Estimated time remaining: ${estimateRemainingTime(feature)}`);
|
|
332
|
+
console.log('');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Approval gates
|
|
336
|
+
if (feature.approvalGates) {
|
|
337
|
+
const gates = Object.entries(feature.approvalGates);
|
|
338
|
+
const approved = gates.filter(([_, g]) => g.approved).length;
|
|
339
|
+
console.log(chalk.white.bold(`Approval Gates: ${approved}/${gates.length} approved`));
|
|
340
|
+
|
|
341
|
+
if (options.verbose) {
|
|
342
|
+
gates.forEach(([gate, info]) => {
|
|
343
|
+
const symbol = info.approved ? '✅' : '⬜';
|
|
344
|
+
const display = info.approved ? chalk.green(gate) : chalk.gray(gate);
|
|
345
|
+
let extra = '';
|
|
346
|
+
if (info.approved && info.approvedBy) {
|
|
347
|
+
extra = chalk.gray(` (by ${info.approvedBy})`);
|
|
348
|
+
}
|
|
349
|
+
console.log(` ${symbol} ${display}${extra}`);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
console.log('');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// Next steps
|
|
356
|
+
const nextSteps = getNextSteps(feature);
|
|
357
|
+
if (nextSteps.length > 0) {
|
|
358
|
+
console.log(chalk.white.bold('Next Steps:'));
|
|
359
|
+
nextSteps.forEach((step, index) => {
|
|
360
|
+
console.log(chalk.yellow(` ${index + 1}. ${step.message}`));
|
|
361
|
+
if (step.command) {
|
|
362
|
+
console.log(chalk.gray(` → ${step.command}`));
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
console.log('');
|
|
366
|
+
} else {
|
|
367
|
+
console.log(chalk.green('✓ All tasks complete!\n'));
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Footer
|
|
371
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
372
|
+
console.log(chalk.gray('Run with --verbose for detailed output'));
|
|
373
|
+
console.log(chalk.gray('Run with --json for JSON output\n'));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export default statusCommand;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* update-agents command
|
|
3
|
+
*
|
|
4
|
+
* Refreshes .claude/agents/ with the latest tier-1 and tier-2 MORPH agents
|
|
5
|
+
* from the framework. Useful after upgrading morph-spec to pick up new or
|
|
6
|
+
* updated agent definitions without re-running full init.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { join, dirname } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { installAgents } from '../../utils/agents-installer.js';
|
|
12
|
+
import { logger } from '../../utils/logger.js';
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const FRAMEWORK_DIR = join(__dirname, '..', '..', '..', 'framework');
|
|
16
|
+
|
|
17
|
+
export async function updateAgentsCommand(args, options) {
|
|
18
|
+
const projectDir = process.cwd();
|
|
19
|
+
|
|
20
|
+
logger.info('Updating native subagents in .claude/agents/...');
|
|
21
|
+
await installAgents(projectDir, FRAMEWORK_DIR);
|
|
22
|
+
logger.success('Native subagents updated. Claude Code will discover them on next session start.');
|
|
23
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { join, dirname } from 'path';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
|
+
import { spawnSync } from 'child_process';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
3
5
|
|
|
4
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
7
|
import fs from 'fs-extra';
|
|
@@ -24,7 +26,9 @@ import {
|
|
|
24
26
|
getUpdateInstructions,
|
|
25
27
|
detectInstallMethod
|
|
26
28
|
} from '../../utils/version-checker.js';
|
|
27
|
-
import { installClaudeHooks } from '../../utils/
|
|
29
|
+
import { installClaudeHooks } from '../../utils/claude-settings-manager.js';
|
|
30
|
+
import { installSkills } from '../../utils/skills-installer.js';
|
|
31
|
+
import { installAgents, installDomainAgents } from '../../utils/agents-installer.js';
|
|
28
32
|
import { AutoContextOrchestrator } from '../../core/orchestrator.js';
|
|
29
33
|
import { detectClaudeCode } from '../../llm/environment-detector.js';
|
|
30
34
|
|
|
@@ -53,8 +57,8 @@ async function backupUserConfig(morphPath) {
|
|
|
53
57
|
*/
|
|
54
58
|
async function cleanFrameworkDirs(morphPath, targetPath) {
|
|
55
59
|
const dirsToClean = [
|
|
56
|
-
join(morphPath, 'templates'),
|
|
57
|
-
join(morphPath, 'standards'),
|
|
60
|
+
join(morphPath, 'framework', 'templates'),
|
|
61
|
+
join(morphPath, 'framework', 'standards'),
|
|
58
62
|
join(morphPath, 'config'),
|
|
59
63
|
join(targetPath, '.claude')
|
|
60
64
|
];
|
|
@@ -115,9 +119,9 @@ export async function updateCommand(options) {
|
|
|
115
119
|
needsInitialization = true;
|
|
116
120
|
|
|
117
121
|
// Create basic .morph structure
|
|
118
|
-
await ensureDir(join(morphPath, '
|
|
119
|
-
await ensureDir(join(morphPath, '
|
|
120
|
-
await ensureDir(join(morphPath, '
|
|
122
|
+
await ensureDir(join(morphPath, 'context'));
|
|
123
|
+
await ensureDir(join(morphPath, 'features'));
|
|
124
|
+
await ensureDir(join(morphPath, 'framework'));
|
|
121
125
|
await ensureDir(join(morphPath, 'config'));
|
|
122
126
|
logger.dim(' ✓ Created .morph directory structure');
|
|
123
127
|
}
|
|
@@ -194,7 +198,7 @@ export async function updateCommand(options) {
|
|
|
194
198
|
if (updateTemplates) {
|
|
195
199
|
updateSpinner.text = 'Updating templates...';
|
|
196
200
|
const templatesSrc = join(contentDir, 'framework', 'templates');
|
|
197
|
-
const templatesDest = join(morphPath, 'templates');
|
|
201
|
+
const templatesDest = join(morphPath, 'framework', 'templates');
|
|
198
202
|
await copyDirectory(templatesSrc, templatesDest);
|
|
199
203
|
}
|
|
200
204
|
|
|
@@ -202,30 +206,31 @@ export async function updateCommand(options) {
|
|
|
202
206
|
if (updateStandards) {
|
|
203
207
|
updateSpinner.text = 'Updating standards...';
|
|
204
208
|
const standardsSrc = join(contentDir, 'framework', 'standards');
|
|
205
|
-
const standardsDest = join(morphPath, 'standards');
|
|
209
|
+
const standardsDest = join(morphPath, 'framework', 'standards');
|
|
206
210
|
await copyDirectory(standardsSrc, standardsDest);
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
// Update agents.json (sourced from framework/ — canonical single source of truth)
|
|
210
214
|
updateSpinner.text = 'Updating agents configuration...';
|
|
211
215
|
const agentsSrc = join(__dirname, '..', '..', '..', 'framework', 'agents.json');
|
|
212
|
-
const agentsDest = join(morphPath, '
|
|
216
|
+
const agentsDest = join(morphPath, 'framework', 'agents.json');
|
|
213
217
|
if (await pathExists(agentsSrc)) {
|
|
214
218
|
await copyFile(agentsSrc, agentsDest);
|
|
215
219
|
}
|
|
216
220
|
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
221
|
+
// Regenerate derived files (phase-utils.js, skill output tables) from output-schema.js
|
|
222
|
+
// Only runs when the generator script is present (framework dev installs via npm link)
|
|
223
|
+
updateSpinner.text = 'Syncing generated refs...';
|
|
224
|
+
try {
|
|
225
|
+
const generateScript = join(__dirname, '..', '..', '..', 'scripts', 'generate-refs.js');
|
|
226
|
+
if (existsSync(generateScript)) {
|
|
227
|
+
const result = spawnSync(process.execPath, [generateScript], { encoding: 'utf8' });
|
|
228
|
+
if (result.status === 0) {
|
|
229
|
+
logger.dim(' ✓ Generated refs synced (phase-utils.js, skill outputs)');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} catch {
|
|
233
|
+
// Non-fatal: generator unavailable or files already in sync
|
|
229
234
|
}
|
|
230
235
|
|
|
231
236
|
// Update .claude commands and skills
|
|
@@ -297,15 +302,40 @@ export async function updateCommand(options) {
|
|
|
297
302
|
}
|
|
298
303
|
}
|
|
299
304
|
|
|
300
|
-
//
|
|
305
|
+
// Sync morph skills to .claude/skills/ for native Claude Code discovery
|
|
306
|
+
updateSpinner.text = 'Syncing morph skills to .claude/skills/...';
|
|
307
|
+
await installSkills(targetPath);
|
|
308
|
+
|
|
309
|
+
// Sync native subagents to .claude/agents/
|
|
310
|
+
updateSpinner.text = 'Syncing agents to .claude/agents/...';
|
|
311
|
+
await installAgents(targetPath, frameworkDir);
|
|
312
|
+
await installDomainAgents(targetPath, frameworkDir);
|
|
313
|
+
|
|
314
|
+
// Sync path-scoped rules to .claude/rules/
|
|
315
|
+
updateSpinner.text = 'Syncing rules to .claude/rules/...';
|
|
316
|
+
const rulesSrc = join(frameworkDir, 'rules');
|
|
317
|
+
const rulesDest = join(claudeDest, 'rules');
|
|
318
|
+
if (await pathExists(rulesSrc)) {
|
|
319
|
+
await copyDirectory(rulesSrc, rulesDest);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Sync runtime CLAUDE.md to .claude/CLAUDE.md
|
|
323
|
+
updateSpinner.text = 'Syncing .claude/CLAUDE.md...';
|
|
324
|
+
const runtimeSrc = join(frameworkDir, 'CLAUDE.md');
|
|
325
|
+
const runtimeDest = join(claudeDest, 'CLAUDE.md');
|
|
326
|
+
if (await pathExists(runtimeSrc)) {
|
|
327
|
+
await copyFile(runtimeSrc, runtimeDest);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Update Claude Code hooks in .claude/settings.local.json
|
|
301
331
|
updateSpinner.text = 'Updating Claude Code hooks...';
|
|
302
|
-
await installClaudeHooks(targetPath);
|
|
332
|
+
const hooksResult = await installClaudeHooks(targetPath);
|
|
303
333
|
|
|
304
334
|
// Update CLAUDE.md
|
|
305
335
|
updateSpinner.text = 'Updating CLAUDE.md...';
|
|
306
|
-
const claudeMdSrc = join(
|
|
336
|
+
const claudeMdSrc = join(frameworkDir, 'CLAUDE.md');
|
|
307
337
|
const claudeMdDest = join(targetPath, 'CLAUDE.md');
|
|
308
|
-
await
|
|
338
|
+
await copyFile(claudeMdSrc, claudeMdDest);
|
|
309
339
|
|
|
310
340
|
// Restore user config after framework reinstallation
|
|
311
341
|
updateSpinner.text = 'Restoring user configuration...';
|
|
@@ -330,10 +360,9 @@ export async function updateCommand(options) {
|
|
|
330
360
|
|
|
331
361
|
logger.blank();
|
|
332
362
|
logger.info('Updated files:');
|
|
333
|
-
if (updateTemplates) logger.dim(' ✓ .morph/templates/');
|
|
334
|
-
if (updateStandards) logger.dim(' ✓ .morph/standards/');
|
|
335
|
-
logger.dim(' ✓ .morph/
|
|
336
|
-
logger.dim(' ✓ .morph/config/azure-pricing.json');
|
|
363
|
+
if (updateTemplates) logger.dim(' ✓ .morph/framework/templates/');
|
|
364
|
+
if (updateStandards) logger.dim(' ✓ .morph/framework/standards/');
|
|
365
|
+
logger.dim(' ✓ .morph/framework/agents.json');
|
|
337
366
|
if (commandsCopied) logger.dim(' ✓ .claude/commands/');
|
|
338
367
|
|
|
339
368
|
if (symlinkCount > 0) {
|
|
@@ -344,7 +373,11 @@ export async function updateCommand(options) {
|
|
|
344
373
|
logger.warn(` ⚠ Directory links not supported (copied instead). Skills won't auto-update.`);
|
|
345
374
|
}
|
|
346
375
|
|
|
347
|
-
logger.dim(
|
|
376
|
+
logger.dim(` ✓ .claude/settings.local.json (${hooksResult.installed} hooks installed)`);
|
|
377
|
+
logger.dim(' ✓ .claude/skills/ (flat .md for /skill-name discovery)');
|
|
378
|
+
logger.dim(' ✓ .claude/agents/ (native subagents refreshed)');
|
|
379
|
+
logger.dim(' ✓ .claude/rules/ (path-scoped rules synced)');
|
|
380
|
+
logger.dim(' ✓ .claude/CLAUDE.md (runtime quick reference)');
|
|
348
381
|
logger.dim(' ✓ CLAUDE.md');
|
|
349
382
|
logger.blank();
|
|
350
383
|
logger.info('Your config.json was preserved.');
|
|
@@ -13,6 +13,7 @@ import chalk from 'chalk';
|
|
|
13
13
|
import { loadState, saveState, getFeature, getApprovalGate } from '../../core/state/state-manager.js';
|
|
14
14
|
import { PHASES, validatePhase } from './validate-phase.js';
|
|
15
15
|
import { detectDesignSystem, hasUIAgentsActive } from '../../lib/detectors/design-system-detector.js';
|
|
16
|
+
import { getOutputPath } from '../../core/paths/output-schema.js';
|
|
16
17
|
import { shouldAutoApprove, autoCalculateTrust } from '../../lib/trust/trust-manager.js';
|
|
17
18
|
import { validateSpec } from '../../lib/validators/spec-validator.js';
|
|
18
19
|
import { validateTransition, getPhaseDisplayName } from '../../core/state/phase-state-machine.js';
|
|
@@ -401,7 +402,7 @@ function getPhaseGuidance(phase, feature) {
|
|
|
401
402
|
],
|
|
402
403
|
'sync': [
|
|
403
404
|
'Review decisions.md for standards to promote',
|
|
404
|
-
`Sync: morph-spec sync --path
|
|
405
|
+
`Sync: morph-spec sync --path ${getOutputPath(feature, 'decisions')}`
|
|
405
406
|
]
|
|
406
407
|
};
|
|
407
408
|
|
|
@@ -437,8 +438,8 @@ function designSystemGate(feature, projectPath = '.') {
|
|
|
437
438
|
'Design system is required when UI agents (blazor-builder, ui-designer, css-specialist) are active',
|
|
438
439
|
'',
|
|
439
440
|
'Create a design system with one of these options:',
|
|
440
|
-
' 1. Project-level: .morph/
|
|
441
|
-
` 2. Feature-level:
|
|
441
|
+
' 1. Project-level: .morph/context/design-system.md (shared across features)',
|
|
442
|
+
` 2. Feature-level: ${getOutputPath(feature, 'uiDesignSystem')} (feature-specific)`,
|
|
442
443
|
' 3. Auto-generate: morph-spec generate design-system (scans existing CSS)',
|
|
443
444
|
'',
|
|
444
445
|
'Or remove UI agents if they are not needed:',
|