@polymorphism-tech/morph-spec 4.12.0 → 4.13.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/README.md +21 -29
- package/bin/morph-spec.js +41 -24
- package/bin/task-manager.js +962 -1341
- package/bin/validate.js +1 -1
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +10 -11
- package/docs/QUICKSTART.md +15 -15
- package/framework/CLAUDE.md +5 -2
- package/framework/agents/README.md +3 -4
- package/framework/agents/ai-agents/ai-system-architect.md +6 -10
- package/framework/agents/architecture/seo-growth-hacker.md +166 -326
- package/framework/agents/architecture/standards-architect.md +21 -31
- package/framework/agents/backend/dotnet-senior.md +160 -86
- package/framework/agents/backend/ef-modeler.md +2 -6
- package/framework/agents/backend/hangfire-orchestrator.md +8 -9
- package/framework/agents/backend/ms-agent-expert.md +1 -1
- package/framework/agents/frontend/nextjs-expert.md +198 -133
- package/framework/agents/frontend/ui-ux-designer.md +226 -267
- package/framework/agents/infrastructure/infra-architect.md +191 -27
- package/framework/agents/integrations/clerk-auth.md +19 -26
- package/framework/agents/integrations/hangfire-integration.md +1 -4
- package/framework/agents.json +215 -1453
- package/framework/commands/morph-apply.md +4 -4
- package/framework/commands/morph-preflight.md +4 -26
- package/framework/commands/morph-proposal.md +19 -19
- package/framework/commands/morph-status.md +2 -2
- package/framework/commands/morph-troubleshoot.md +6 -13
- package/framework/hooks/README.md +1 -6
- package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +4 -6
- package/framework/hooks/claude-code/pre-compact/save-morph-context.js +12 -7
- package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +2 -2
- package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +2 -2
- package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +5 -10
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +63 -30
- package/framework/hooks/claude-code/session-start/resume-context.js +77 -0
- package/framework/hooks/claude-code/statusline.py +4 -5
- package/framework/hooks/claude-code/stop/validate-completion.js +4 -4
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +8 -8
- package/framework/hooks/shared/compact-restore.js +28 -5
- package/framework/hooks/shared/phase-utils.js +4 -8
- package/framework/hooks/shared/state-reader.js +34 -3
- package/framework/phases.json +7 -45
- package/framework/rules/ai-agents-standards.md +15 -0
- package/framework/rules/asaas-standards.md +13 -0
- package/framework/rules/clerk-standards.md +13 -0
- package/framework/rules/csharp-standards.md +8 -4
- package/framework/rules/data-standards.md +18 -0
- package/framework/rules/dotnet-templates.md +87 -0
- package/framework/rules/frontend-standards.md +13 -13
- package/framework/rules/hangfire-standards.md +13 -0
- package/framework/rules/infrastructure-standards.md +27 -16
- package/framework/rules/morph-workflow.md +73 -13
- package/framework/rules/nextjs-standards.md +1 -0
- package/framework/rules/nextjs-templates.md +40 -0
- package/framework/rules/resend-standards.md +12 -0
- package/framework/rules/supabase-standards.md +29 -0
- package/framework/skills/README.md +6 -8
- package/framework/skills/level-0-meta/mcp-registry.json +21 -99
- package/framework/{standards/ai-agents/team-orchestration.md → skills/level-0-meta/morph-agent-teams/SKILL.md} +472 -479
- package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +28 -1
- package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
- package/framework/skills/level-0-meta/morph-code-review/SKILL.md +1 -5
- package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +1 -1
- package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +23 -41
- package/framework/skills/level-0-meta/morph-init/SKILL.md +18 -14
- package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +225 -0
- package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +20 -0
- package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +4 -8
- package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +15 -59
- package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +7 -19
- package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +8 -8
- package/framework/skills/level-1-workflows/README.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +49 -50
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +58 -124
- package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +5 -50
- package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +127 -159
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +4 -3
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +2 -2
- package/framework/skills/level-1-workflows/morph-phase-implement/references/recap-example.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +17 -13
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +22 -40
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +0 -2
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/tasks-example.md +5 -5
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +57 -77
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/framework/squad-templates/backend-only.json +6 -6
- package/framework/squad-templates/frontend-only.json +17 -8
- package/framework/squad-templates/full-stack.json +29 -24
- package/framework/standards/STANDARDS.json +1021 -2369
- package/framework/standards/backend/dotnet/fluent-validation-vsa.md +200 -0
- package/framework/standards/backend/dotnet/result-pattern.md +213 -0
- package/framework/standards/backend/dotnet/scalar-ui.md +172 -0
- package/framework/standards/backend/dotnet/scrutor.md +158 -0
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -0
- package/framework/standards/frontend/nextjs/motion-patterns.md +1 -1
- package/framework/standards/infrastructure/supabase/mcp-setup.md +83 -193
- package/framework/standards/integration/mcp/mcp-tools.md +91 -77
- package/framework/templates/IDE-SNIPPETS.md +2 -6
- package/framework/templates/README.md +709 -814
- package/framework/templates/REGISTRY.json +223 -762
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -0
- package/framework/templates/code/dotnet/abstractions/error.cs +60 -0
- package/framework/templates/code/dotnet/abstractions/handler.cs +12 -0
- package/framework/templates/code/dotnet/abstractions/result.cs +74 -0
- package/framework/templates/code/dotnet/backend/repository.cs +148 -141
- package/framework/templates/code/dotnet/constants/api-tags.cs +6 -0
- package/framework/templates/code/dotnet/exceptions/exception-handler.cs +32 -0
- package/framework/templates/code/dotnet/extensions/database-extensions.cs +20 -0
- package/framework/templates/code/dotnet/extensions/handler-registration.cs +38 -0
- package/framework/templates/code/dotnet/extensions/health-checks.cs +24 -0
- package/framework/templates/code/dotnet/extensions/map-endpoints.cs +35 -0
- package/framework/templates/code/dotnet/extensions/result-extensions.cs +29 -0
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -0
- package/framework/templates/code/dotnet/feature/entity.cs.hbs +8 -0
- package/framework/templates/code/dotnet/feature/errors.cs.hbs +8 -0
- package/framework/templates/code/dotnet/feature/handler.cs.hbs +24 -0
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -0
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -0
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -0
- package/framework/templates/code/dotnet/jobs/job.cs +21 -17
- package/framework/templates/code/dotnet/pipelines/logging-decorator.cs +31 -0
- package/framework/templates/code/dotnet/pipelines/validation-decorator.cs +97 -0
- package/framework/templates/code/dotnet/test.cs +192 -106
- package/framework/templates/context/ARCHITECTURE.md +89 -0
- package/framework/templates/context/CONTEXT-FEATURE.md +2 -2
- package/framework/templates/context/CONTEXT.md +180 -181
- package/framework/templates/context/design-system.md +1 -5
- package/framework/templates/docs/onboarding.md +2 -3
- package/framework/templates/docs/proposal.md +171 -182
- package/framework/templates/docs/spec.md +1 -3
- package/framework/templates/docs/ui-components.md +0 -72
- package/framework/templates/examples/design-system-examples.md +4 -4
- package/framework/templates/feature/decisions.md +0 -66
- package/framework/templates/feature/recap.md +1 -2
- package/framework/templates/infrastructure/github/README.md +56 -593
- package/framework/templates/integrations/clerk-config.cs +0 -41
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -2
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +83 -126
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +2 -2
- package/framework/templates/project/validate.js +2 -4
- package/framework/templates/ui/design-system.css +1 -1
- package/framework/workflows/README.md +8 -8
- package/framework/workflows/configs/fast-track.json +51 -0
- package/framework/workflows/configs/full.json +68 -0
- package/framework/workflows/configs/standard.json +7 -3
- package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +1 -1
- package/framework/workflows/docs/enforcement-pipeline.md +18 -19
- package/framework/workflows/docs/full-morph.md +69 -76
- package/framework/workflows/docs/standard.md +49 -44
- package/framework/workflows/docs/ui-refresh.md +1 -1
- package/package.json +3 -3
- package/src/commands/agents/dispatch-agents.js +55 -116
- package/src/commands/context/context-refresh.js +79 -0
- package/src/commands/phase/phase-reset.js +1 -1
- package/src/commands/project/doctor.js +10 -32
- package/src/commands/project/init.js +12 -0
- package/src/commands/project/status.js +6 -12
- package/src/commands/scaffold/scaffold.js +131 -0
- package/src/commands/scope/escalate.js +1 -1
- package/src/commands/state/advance-phase.js +15 -29
- package/src/commands/state/state.js +20 -5
- package/src/commands/tasks/task.js +0 -30
- package/src/commands/validation/validate-feature.js +3 -10
- package/src/core/paths/output-schema.js +12 -13
- package/src/core/state/phase-state-machine.js +211 -217
- package/src/core/state/state-manager.js +9 -9
- package/src/lib/agents/agents-manager.js +2 -2
- package/src/lib/agents/output-collector.js +1 -2
- package/src/lib/detectors/design-system-detector.js +4 -4
- package/src/lib/detectors/index.js +1 -11
- package/src/lib/generators/architecture-scanner.js +640 -0
- package/src/lib/generators/context-generator.js +3 -3
- package/src/lib/generators/design-system-generator.js +508 -587
- package/src/lib/generators/index.js +12 -10
- package/src/lib/generators/metadata-extractor.js +386 -387
- package/src/lib/generators/recap-generator.js +4 -4
- package/src/lib/generators/scaffold-generator.js +317 -0
- package/src/lib/generators/settings-generator.js +0 -1
- package/src/lib/phase-chain/phase-validator.js +64 -42
- package/src/lib/stack/stack-profile.js +2 -2
- package/src/lib/standards/digest-builder.js +72 -285
- package/src/lib/tasks/task-parser.js +11 -5
- package/src/lib/validators/architecture/architecture-validator.js +259 -387
- package/src/lib/validators/content/content-validator.js +287 -287
- package/src/lib/validators/css/css-validator.js +340 -352
- package/src/lib/validators/packages/package-validator.js +347 -360
- package/src/lib/validators/shared/issue-counter.js +14 -18
- package/src/lib/validators/validation-runner.js +3 -19
- package/src/scripts/setup-infra.js +1 -1
- package/src/utils/agents-installer.js +24 -3
- package/src/utils/file-copier.js +1 -0
- package/src/utils/hooks-installer.js +11 -19
- package/src/utils/skills-installer.js +178 -178
- package/framework/agents/architecture/prompt-engineer.md +0 -195
- package/framework/agents/backend/api-designer.md +0 -106
- package/framework/agents/frontend/blazor-builder.md +0 -229
- package/framework/agents/frontend/nextjs-ui-specialist.md +0 -218
- package/framework/agents/infrastructure/azure-architect.md +0 -150
- package/framework/agents/infrastructure/azure-deploy-specialist.md +0 -707
- package/framework/agents/infrastructure/bicep-architect.md +0 -132
- package/framework/agents/infrastructure/container-specialist.md +0 -137
- package/framework/agents/infrastructure/devops-engineer.md +0 -126
- package/framework/agents/integrations/azure-identity.md +0 -148
- package/framework/agents/quality/code-analyzer.md +0 -239
- package/framework/agents/quality/testing-specialist.md +0 -130
- package/framework/hooks/claude-code/notification/approval-reminder.js +0 -57
- package/framework/hooks/claude-code/post-tool-use/context-refresh.js +0 -109
- package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +0 -78
- package/framework/index/troubleshooting-index.json +0 -184
- package/framework/rules/testing-standards.md +0 -14
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +0 -230
- package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +0 -70
- package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +0 -256
- package/framework/skills/level-1-workflows/morph-phase-clarify/references/clarifications-example.md +0 -117
- package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +0 -269
- package/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
- package/framework/standards/architecture/ddd/complexity-levels.md +0 -108
- package/framework/standards/architecture/ddd/entities.md +0 -99
- package/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
- package/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/framework/standards/backend/api/minimal-api.md +0 -494
- package/framework/standards/backend/api/rest.md +0 -492
- package/framework/standards/backend/authentication/passkeys.md +0 -428
- package/framework/standards/backend/database/ef-core.md +0 -199
- package/framework/standards/backend/database/migrations.md +0 -393
- package/framework/standards/backend/database/repository-patterns.md +0 -528
- package/framework/standards/backend/dotnet/async.md +0 -366
- package/framework/standards/backend/dotnet/core.md +0 -117
- package/framework/standards/backend/dotnet/di.md +0 -439
- package/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/framework/standards/context/analytics.md +0 -96
- package/framework/standards/context/bundles.md +0 -110
- package/framework/standards/context/priming.md +0 -78
- package/framework/standards/core/architecture.md +0 -185
- package/framework/standards/core/coding.md +0 -214
- package/framework/standards/core/git-branching-strategy.md +0 -403
- package/framework/standards/core/git.md +0 -185
- package/framework/standards/core/testing.md +0 -295
- package/framework/standards/data/nosql/blob-storage.md +0 -102
- package/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/framework/standards/frontend/blazor/state.md +0 -191
- package/framework/standards/frontend/design-system/aesthetic-direction.md +0 -266
- package/framework/standards/frontend/design-system/design-trends.md +0 -171
- package/framework/standards/infrastructure/azure/azure.md +0 -624
- package/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/framework/standards/infrastructure/vercel/vercel-database.md +0 -106
- package/framework/standards/integration/api/graphql.md +0 -91
- package/framework/standards/integration/api/grpc.md +0 -114
- package/framework/standards/integration/api/rest-design.md +0 -95
- package/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/framework/standards/observability/logging.md +0 -131
- package/framework/standards/observability/metrics.md +0 -121
- package/framework/standards/observability/monitoring.md +0 -114
- package/framework/standards/observability/tracing.md +0 -132
- package/framework/standards/workflows/parallel-execution.md +0 -112
- package/framework/standards/workflows/thread-management.md +0 -113
- package/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
- package/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
- package/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
- package/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/framework/templates/infrastructure/azure/README.md +0 -286
- package/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/framework/templates/project-structure/dotnet-ddd.md +0 -70
- package/framework/templates/saas/subscription.cs +0 -347
- package/framework/templates/saas/tenant.cs +0 -338
- package/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/framework/templates/ui/MudTheme.cs +0 -281
- package/framework/workflows/configs/nodejs-cli.json +0 -40
- package/src/commands/standards/context-budget.js +0 -89
- package/src/lib/standards/index.js +0 -7
- package/src/lib/standards/standards-context-injector.js +0 -302
- package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +0 -316
- package/src/lib/validators/blazor/blazor-state-validator.js +0 -279
- package/src/lib/validators/blazor/blazor-validator.js +0 -369
- package/src/lib/validators/blazor/index.js +0 -9
|
@@ -94,40 +94,20 @@ const REQUIRED_COMMAND_FILES = [
|
|
|
94
94
|
'src/lib/scope/impact-analyzer.js'
|
|
95
95
|
];
|
|
96
96
|
|
|
97
|
-
// framework standards
|
|
97
|
+
// framework standards (stack-relevant only)
|
|
98
98
|
const FRAMEWORK_STANDARDS = [
|
|
99
|
-
'framework/standards/
|
|
100
|
-
'framework/standards/observability/logging.md',
|
|
101
|
-
'framework/standards/observability/tracing.md',
|
|
102
|
-
'framework/standards/observability/metrics.md',
|
|
103
|
-
'framework/standards/integration/event-driven/service-bus.md',
|
|
104
|
-
'framework/standards/integration/event-driven/cqrs.md',
|
|
105
|
-
'framework/standards/integration/event-driven/event-sourcing.md',
|
|
99
|
+
'framework/standards/architecture/vertical-slice/vertical-slice.md',
|
|
106
100
|
'framework/standards/data/nosql/cosmos-db.md',
|
|
107
101
|
'framework/standards/data/nosql/cache/redis.md',
|
|
108
|
-
'framework/standards/data/nosql/blob-storage.md',
|
|
109
|
-
'framework/standards/integration/api/rest-design.md',
|
|
110
|
-
'framework/standards/integration/api/graphql.md',
|
|
111
|
-
'framework/standards/integration/api/grpc.md',
|
|
112
|
-
'framework/standards/architecture/ddd/aggregates.md',
|
|
113
|
-
'framework/standards/architecture/ddd/entities.md',
|
|
114
|
-
'framework/standards/architecture/ddd/value-objects.md',
|
|
115
|
-
'framework/standards/architecture/vertical-slice/vertical-slice.md',
|
|
116
|
-
'framework/standards/data/vector-search/azure-ai-search.md',
|
|
117
102
|
'framework/standards/data/vector-search/rag-chunking.md',
|
|
118
|
-
'framework/standards/
|
|
119
|
-
'framework/standards/context/bundles.md',
|
|
120
|
-
'framework/standards/context/analytics.md',
|
|
103
|
+
'framework/standards/integration/mcp/mcp-tools.md',
|
|
121
104
|
'framework/standards/workflows/thread-management.md',
|
|
122
105
|
'framework/standards/workflows/parallel-execution.md'
|
|
123
106
|
];
|
|
124
107
|
|
|
125
108
|
// required agents expected in agents.json
|
|
126
109
|
const REQUIRED_AGENTS = [
|
|
127
|
-
'vector-search-expert'
|
|
128
|
-
'thread-orchestrator',
|
|
129
|
-
'context-optimizer',
|
|
130
|
-
'observability-expert'
|
|
110
|
+
'vector-search-expert'
|
|
131
111
|
];
|
|
132
112
|
|
|
133
113
|
/**
|
|
@@ -585,7 +565,7 @@ export async function doctorCommand(options = {}) {
|
|
|
585
565
|
}
|
|
586
566
|
|
|
587
567
|
// Check 2: required tier-2 agents present
|
|
588
|
-
const requiredTier2 = ['standards-architect', 'dotnet-senior', 'infra-architect'
|
|
568
|
+
const requiredTier2 = ['standards-architect', 'dotnet-senior', 'infra-architect'];
|
|
589
569
|
const missingTier2 = requiredTier2.filter(id => !agentsData.agents[id]);
|
|
590
570
|
if (missingTier2.length > 0) {
|
|
591
571
|
checks.push({
|
|
@@ -671,15 +651,13 @@ export async function doctorCommand(options = {}) {
|
|
|
671
651
|
const standardsPath = join(morphPath, 'framework', 'standards');
|
|
672
652
|
const frameworkStdsRoot = join(import.meta.dirname, '..', '..', '..', 'framework', 'standards');
|
|
673
653
|
if (await pathExists(standardsPath)) {
|
|
674
|
-
// Check for
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
await pathExists(join(standardsPath, 'architecture.md'));
|
|
679
|
-
if (codingStd && archStd) {
|
|
654
|
+
// Check for VSA standard (core to the framework)
|
|
655
|
+
const vsaStd = await pathExists(join(standardsPath, 'architecture', 'vertical-slice', 'vertical-slice.md')) ||
|
|
656
|
+
await pathExists(join(standardsPath, 'vertical-slice.md'));
|
|
657
|
+
if (vsaStd) {
|
|
680
658
|
checks.push({ name: 'standards/', status: 'ok' });
|
|
681
659
|
} else {
|
|
682
|
-
checks.push({ name: 'standards/', status: 'warn', msg: '
|
|
660
|
+
checks.push({ name: 'standards/', status: 'warn', msg: 'VSA standard missing — run morph-spec init' });
|
|
683
661
|
hasWarnings = true;
|
|
684
662
|
}
|
|
685
663
|
} else if (await pathExists(frameworkStdsRoot)) {
|
|
@@ -365,6 +365,18 @@ export async function initCommand(options) {
|
|
|
365
365
|
logger.dim('\nSkipped MCP setup (--skip-mcp flag)');
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
+
// Auto-generate architecture context (non-blocking on failure)
|
|
369
|
+
spinner.text = 'Generating architecture context...';
|
|
370
|
+
try {
|
|
371
|
+
const { scanArchitecture, renderArchitectureContext } = await import('../../lib/generators/architecture-scanner.js');
|
|
372
|
+
const scanResult = await scanArchitecture(targetPath);
|
|
373
|
+
await renderArchitectureContext(targetPath, scanResult);
|
|
374
|
+
spinner.succeed('Architecture context generated');
|
|
375
|
+
} catch {
|
|
376
|
+
// Non-fatal: placeholder README.md remains
|
|
377
|
+
spinner.warn('Architecture context generation skipped');
|
|
378
|
+
}
|
|
379
|
+
|
|
368
380
|
spinner.succeed('MORPH-SPEC installed successfully!');
|
|
369
381
|
|
|
370
382
|
// Show next steps
|
|
@@ -31,13 +31,12 @@ const PHASE_SYMBOLS = {
|
|
|
31
31
|
*/
|
|
32
32
|
const PHASE_ORDER = [
|
|
33
33
|
{ key: 'proposal', name: 'FASE 0: PROPOSAL', order: 0 },
|
|
34
|
-
{ key: '
|
|
35
|
-
{ key: '
|
|
36
|
-
{ key: '
|
|
37
|
-
{ key: '
|
|
38
|
-
{ key: '
|
|
39
|
-
{ key: '
|
|
40
|
-
{ key: 'sync', name: 'FASE 6: SYNC', order: 7, optional: true }
|
|
34
|
+
{ key: 'uiux', name: 'FASE 1: UI/UX', order: 1, optional: true },
|
|
35
|
+
{ key: 'design', name: 'FASE 2: DESIGN', order: 2 },
|
|
36
|
+
{ key: 'plan', name: 'FASE 3: PLAN', order: 3 },
|
|
37
|
+
{ key: 'tasks', name: 'FASE 4: TASKS', order: 4 },
|
|
38
|
+
{ key: 'implement', name: 'FASE 5: IMPLEMENT', order: 5 },
|
|
39
|
+
{ key: 'sync', name: 'FASE 6: SYNC', order: 6, optional: true }
|
|
41
40
|
];
|
|
42
41
|
|
|
43
42
|
/**
|
|
@@ -69,7 +68,6 @@ function checkPhaseOutputs(phaseKey, feature) {
|
|
|
69
68
|
proposal: ['proposal'],
|
|
70
69
|
uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
|
|
71
70
|
design: ['spec', 'contracts', 'schemaAnalysis', 'decisions'],
|
|
72
|
-
clarify: ['clarifications'],
|
|
73
71
|
tasks: ['tasks']
|
|
74
72
|
};
|
|
75
73
|
|
|
@@ -107,7 +105,6 @@ function formatPhase(phaseKey, currentPhase, feature, options = {}) {
|
|
|
107
105
|
proposal: ['proposal'],
|
|
108
106
|
uiux: ['uiDesignSystem', 'uiMockups', 'uiComponents', 'uiFlows'],
|
|
109
107
|
design: ['spec', 'contracts', 'schemaAnalysis', 'decisions'],
|
|
110
|
-
clarify: ['clarifications'],
|
|
111
108
|
tasks: ['tasks'],
|
|
112
109
|
implement: ['recap']
|
|
113
110
|
};
|
|
@@ -145,10 +142,8 @@ function getNextSteps(feature) {
|
|
|
145
142
|
// Check for pending approvals relevant to current phase
|
|
146
143
|
const phaseApprovalMap = {
|
|
147
144
|
proposal: 'proposal',
|
|
148
|
-
setup: 'proposal',
|
|
149
145
|
uiux: 'uiux',
|
|
150
146
|
design: 'design',
|
|
151
|
-
clarify: 'design',
|
|
152
147
|
tasks: 'tasks',
|
|
153
148
|
implement: 'tasks'
|
|
154
149
|
};
|
|
@@ -168,7 +163,6 @@ function getNextSteps(feature) {
|
|
|
168
163
|
const phaseOutputMap = {
|
|
169
164
|
proposal: ['proposal'],
|
|
170
165
|
design: ['spec', 'contracts'],
|
|
171
|
-
clarify: ['clarifications'],
|
|
172
166
|
tasks: ['tasks'],
|
|
173
167
|
implement: ['recap']
|
|
174
168
|
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold Command - Generate feature files from templates.
|
|
3
|
+
*
|
|
4
|
+
* Sub-commands:
|
|
5
|
+
* - scaffold dotnet <feature> <slice-name> — VSA feature slice (.NET)
|
|
6
|
+
* - scaffold nextjs <feature> — Feature page + components (Next.js)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { relative } from 'path';
|
|
11
|
+
import { logger } from '../../utils/logger.js';
|
|
12
|
+
import {
|
|
13
|
+
scaffoldDotnetSlice,
|
|
14
|
+
scaffoldNextjsFeature,
|
|
15
|
+
detectNamespace,
|
|
16
|
+
} from '../../lib/generators/scaffold-generator.js';
|
|
17
|
+
|
|
18
|
+
const KEBAB_REGEX = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validate that a name is valid kebab-case.
|
|
22
|
+
* @param {string} name
|
|
23
|
+
* @param {string} label
|
|
24
|
+
*/
|
|
25
|
+
function validateKebabCase(name, label) {
|
|
26
|
+
if (!KEBAB_REGEX.test(name)) {
|
|
27
|
+
logger.error(`Invalid ${label}: "${name}"`);
|
|
28
|
+
logger.dim('Must be kebab-case (e.g., "book", "create-user", "user-profile")');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Log the result of a scaffold operation.
|
|
35
|
+
* @param {Array<{path: string, skipped: boolean}>} files
|
|
36
|
+
* @param {string} outputDir
|
|
37
|
+
*/
|
|
38
|
+
function logResult(files, outputDir) {
|
|
39
|
+
let created = 0;
|
|
40
|
+
let skipped = 0;
|
|
41
|
+
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const rel = relative(outputDir, file.path);
|
|
44
|
+
if (file.skipped) {
|
|
45
|
+
logger.dim(`⊘ ${rel} (already exists)`);
|
|
46
|
+
skipped++;
|
|
47
|
+
} else {
|
|
48
|
+
logger.success(rel);
|
|
49
|
+
created++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
logger.blank();
|
|
54
|
+
const parts = [`${created} files generated`];
|
|
55
|
+
if (skipped > 0) parts.push(`${skipped} skipped`);
|
|
56
|
+
logger.info(parts.join(', '));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Scaffold .NET VSA feature slice.
|
|
61
|
+
*/
|
|
62
|
+
export async function scaffoldDotnetCommand(feature, sliceName, options) {
|
|
63
|
+
validateKebabCase(feature, 'feature name');
|
|
64
|
+
validateKebabCase(sliceName, 'slice name');
|
|
65
|
+
|
|
66
|
+
const outputDir = options.outputDir || process.cwd();
|
|
67
|
+
|
|
68
|
+
// Detect or use provided namespace
|
|
69
|
+
const namespace = options.namespace || detectNamespace(outputDir);
|
|
70
|
+
if (!namespace) {
|
|
71
|
+
logger.error('Could not detect namespace');
|
|
72
|
+
logger.dim('No .csproj or .morph/config.json found. Use --namespace <ns> to specify.');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const pascalFeature = feature.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
|
|
77
|
+
const pascalSlice = sliceName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
|
|
78
|
+
|
|
79
|
+
logger.header('Scaffolding .NET VSA Slice');
|
|
80
|
+
logger.dim(`Feature: ${pascalFeature}`);
|
|
81
|
+
logger.dim(`Slice: ${pascalSlice}`);
|
|
82
|
+
logger.dim(`Namespace: ${namespace}`);
|
|
83
|
+
if (options.dryRun) logger.info(chalk.cyan('DRY RUN — files will NOT be written'));
|
|
84
|
+
logger.blank();
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const result = scaffoldDotnetSlice({
|
|
88
|
+
feature,
|
|
89
|
+
sliceName,
|
|
90
|
+
namespace,
|
|
91
|
+
outputDir,
|
|
92
|
+
dryRun: options.dryRun || false,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
logResult(result.files, outputDir);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
logger.error(`Scaffold failed: ${error.message}`);
|
|
98
|
+
if (options.verbose) console.error(error.stack);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Scaffold Next.js feature page with components and hooks.
|
|
105
|
+
*/
|
|
106
|
+
export async function scaffoldNextjsCommand(feature, options) {
|
|
107
|
+
validateKebabCase(feature, 'feature name');
|
|
108
|
+
|
|
109
|
+
const outputDir = options.outputDir || process.cwd();
|
|
110
|
+
|
|
111
|
+
const pascalFeature = feature.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
|
|
112
|
+
|
|
113
|
+
logger.header('Scaffolding Next.js Feature');
|
|
114
|
+
logger.dim(`Feature: ${pascalFeature}`);
|
|
115
|
+
if (options.dryRun) logger.info(chalk.cyan('DRY RUN — files will NOT be written'));
|
|
116
|
+
logger.blank();
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const result = scaffoldNextjsFeature({
|
|
120
|
+
featureName: feature,
|
|
121
|
+
outputDir,
|
|
122
|
+
dryRun: options.dryRun || false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
logResult(result.files, outputDir);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
logger.error(`Scaffold failed: ${error.message}`);
|
|
128
|
+
if (options.verbose) console.error(error.stack);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -51,7 +51,7 @@ export async function escalateScope(featureName, options) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Read spec.md (optional — not all features have it)
|
|
54
|
-
const specPath = join(process.cwd(), '.morph', 'features', featureName, '
|
|
54
|
+
const specPath = join(process.cwd(), '.morph', 'features', featureName, '2-design', 'spec.md');
|
|
55
55
|
let specMd = '';
|
|
56
56
|
try { specMd = readFileSync(specPath, 'utf-8'); } catch { /* ok */ }
|
|
57
57
|
|
|
@@ -28,7 +28,7 @@ import { emitValidatorDispatch } from '../../lib/validators/shared/emit-validato
|
|
|
28
28
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
29
|
|
|
30
30
|
// Phase order for advancing (skips optional phases unless active)
|
|
31
|
-
const PHASE_ORDER = ['proposal', '
|
|
31
|
+
const PHASE_ORDER = ['proposal', 'uiux', 'design', 'plan', 'tasks', 'implement', 'sync'];
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Phases that require an explicit approval gate before advancing.
|
|
@@ -59,7 +59,7 @@ function getNextPhase(currentPhase, feature, skipOptional, featureName) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Agents that justify the uiux phase (wireframes, design system).
|
|
62
|
-
// Implementation-only agents (
|
|
62
|
+
// Implementation-only agents (nextjs-expert) are NOT included —
|
|
63
63
|
// they build components from existing designs but don't create the design artifacts.
|
|
64
64
|
const uiDesignAgents = ['uiux-designer', 'ui-ux-designer', 'ui-designer'];
|
|
65
65
|
|
|
@@ -189,8 +189,15 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
189
189
|
console.log(chalk.gray('Next Phase:'), nextPhaseDef.name);
|
|
190
190
|
|
|
191
191
|
// === GATE 1: State Machine Validation ===
|
|
192
|
-
//
|
|
193
|
-
|
|
192
|
+
// When a workflow config defines which phases to run, getNextPhase()
|
|
193
|
+
// is authoritative for phase navigation. The state machine's
|
|
194
|
+
// adjacent-only transitions would reject legitimate workflow skips
|
|
195
|
+
// (e.g., fast-track: proposal → tasks).
|
|
196
|
+
const activeWorkflowConfig = featureData.workflow && featureData.workflow !== 'auto'
|
|
197
|
+
? getWorkflowConfig(featureData.workflow)
|
|
198
|
+
: null;
|
|
199
|
+
|
|
200
|
+
if (!options.force && !activeWorkflowConfig) {
|
|
194
201
|
try {
|
|
195
202
|
validateTransition(currentPhase, nextPhase);
|
|
196
203
|
} catch (error) {
|
|
@@ -261,7 +268,7 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
261
268
|
|
|
262
269
|
// === GATE 4: Content Validation ===
|
|
263
270
|
// Validate spec.md and contracts.cs when advancing from design phase
|
|
264
|
-
if (currentPhase === 'design' &&
|
|
271
|
+
if (currentPhase === 'design' && nextPhase === 'plan') {
|
|
265
272
|
// Check spec.md structure and content (filesystem-based)
|
|
266
273
|
const specAbsPath = getAbsoluteOutputPath(process.cwd(), feature, 'spec');
|
|
267
274
|
if (existsSync(specAbsPath)) {
|
|
@@ -334,19 +341,6 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
334
341
|
}
|
|
335
342
|
}
|
|
336
343
|
|
|
337
|
-
// === GATE 6: Clarifications Required ===
|
|
338
|
-
// When advancing FROM clarify, clarifications.md must exist.
|
|
339
|
-
// This enforces that morph-phase-clarify was actually run (not just skipped).
|
|
340
|
-
if (currentPhase === 'clarify') {
|
|
341
|
-
const clarPath = join(process.cwd(), '.morph', 'features', feature, '1-design', 'clarifications.md');
|
|
342
|
-
if (!existsSync(clarPath)) {
|
|
343
|
-
console.log(chalk.red('\n✗ Cannot advance from clarify — clarifications.md is missing'));
|
|
344
|
-
console.log(chalk.yellow(' Run the phase-clarify skill first: /morph-phase-clarify'));
|
|
345
|
-
console.log(chalk.gray(' Output expected at: .morph/features/' + feature + '/1-design/clarifications.md\n'));
|
|
346
|
-
process.exit(1);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
344
|
// Gate: Check design system when advancing to implement with UI agents
|
|
351
345
|
if (nextPhase === 'implement') {
|
|
352
346
|
const gateResult = designSystemGate(feature, process.cwd());
|
|
@@ -373,7 +367,7 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
373
367
|
|
|
374
368
|
// Create the target phase directory so derivePhase() reflects the new phase
|
|
375
369
|
const PHASE_DIR_MAP = {
|
|
376
|
-
'proposal': '0-proposal', 'design': '
|
|
370
|
+
'proposal': '0-proposal', 'design': '2-design', 'uiux': '1-ui',
|
|
377
371
|
'plan': '3-plan', 'tasks': '4-tasks', 'implement': '5-implement',
|
|
378
372
|
};
|
|
379
373
|
const targetDir = PHASE_DIR_MAP[nextPhase];
|
|
@@ -488,10 +482,6 @@ export async function advancePhaseCommand(feature, options = {}) {
|
|
|
488
482
|
*/
|
|
489
483
|
function getPhaseGuidance(phase, feature) {
|
|
490
484
|
const guides = {
|
|
491
|
-
'setup': [
|
|
492
|
-
`Resume spec pipeline: /morph-proposal ${feature}`,
|
|
493
|
-
'Auto-continues from setup phase'
|
|
494
|
-
],
|
|
495
485
|
'uiux': [
|
|
496
486
|
`Resume spec pipeline: /morph-proposal ${feature}`,
|
|
497
487
|
'Provide layout references and preferences',
|
|
@@ -505,10 +495,6 @@ function getPhaseGuidance(phase, feature) {
|
|
|
505
495
|
isDotnet ? 'Approve spec.md and contracts.cs' : 'Approve spec.md and contracts.ts (TypeScript + Zod schemas)'
|
|
506
496
|
];
|
|
507
497
|
})(),
|
|
508
|
-
'clarify': [
|
|
509
|
-
`Resume spec pipeline: /morph-proposal ${feature}`,
|
|
510
|
-
'Resolve edge cases and unknowns'
|
|
511
|
-
],
|
|
512
498
|
'plan': [
|
|
513
499
|
`Resume spec pipeline: /morph-proposal ${feature}`,
|
|
514
500
|
'Review implementation plan for completeness',
|
|
@@ -559,7 +545,7 @@ function designSystemGate(feature, projectPath = '.') {
|
|
|
559
545
|
blocked: true,
|
|
560
546
|
message: 'Cannot advance to implementation — UI agents are active but no design system found',
|
|
561
547
|
solution: [
|
|
562
|
-
'Design system is required when UI agents (
|
|
548
|
+
'Design system is required when UI agents (ui-designer, css-specialist) are active',
|
|
563
549
|
'',
|
|
564
550
|
'Create a design system with one of these options:',
|
|
565
551
|
' 1. Project-level: .morph/context/design-system.md (shared across features)',
|
|
@@ -567,7 +553,7 @@ function designSystemGate(feature, projectPath = '.') {
|
|
|
567
553
|
' 3. Run /morph-phase-uiux skill to auto-generate from existing codebase',
|
|
568
554
|
'',
|
|
569
555
|
'Or remove UI agents if they are not needed:',
|
|
570
|
-
` morph-spec state remove-agent ${feature}
|
|
556
|
+
` morph-spec state remove-agent ${feature} css-specialist`
|
|
571
557
|
]
|
|
572
558
|
};
|
|
573
559
|
}
|
|
@@ -15,7 +15,7 @@ import { derivePhase } from '../../core/state/state-manager.js';
|
|
|
15
15
|
// Phase Resolution
|
|
16
16
|
// ============================================================================
|
|
17
17
|
|
|
18
|
-
const PHASE_ORDER_LIST = ['
|
|
18
|
+
const PHASE_ORDER_LIST = ['proposal', 'uiux', 'design', 'plan', 'tasks', 'implement', 'sync', 'archived'];
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Resolve the effective phase: pick whichever is further ahead between the
|
|
@@ -38,7 +38,7 @@ function resolvePhase(storedPhase, derivedPhase) {
|
|
|
38
38
|
* These phases must be reached through `morph-spec phase advance` which enforces
|
|
39
39
|
* all validation gates (approval, output requirements, spec content, etc.).
|
|
40
40
|
*
|
|
41
|
-
* Lightweight phases (proposal,
|
|
41
|
+
* Lightweight phases (proposal, sync) are not in this list
|
|
42
42
|
* because they have no approval gates and are safe to set directly.
|
|
43
43
|
*/
|
|
44
44
|
export const PROTECTED_PHASES = ['design', 'tasks', 'uiux', 'implement'];
|
|
@@ -244,13 +244,29 @@ async function setCommand(featureName, key, value, options) {
|
|
|
244
244
|
} else {
|
|
245
245
|
logger.warn(`Direct phase override — validation gates may be bypassed.`);
|
|
246
246
|
logger.dim(` The actual phase is derived from filesystem subdirectories`);
|
|
247
|
-
logger.dim(` (0-proposal/,
|
|
248
|
-
logger.dim(` override used only for lightweight phases (
|
|
247
|
+
logger.dim(` (0-proposal/, 2-design/, 4-tasks/, 5-implement/). This sets a state.json`);
|
|
248
|
+
logger.dim(` override used only for lightweight phases (proposal, sync).`);
|
|
249
249
|
logger.dim(` Recommended: morph-spec phase advance ${featureName}`);
|
|
250
250
|
}
|
|
251
251
|
logger.blank();
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
// Validate workflow values
|
|
255
|
+
if (key === 'workflow') {
|
|
256
|
+
try {
|
|
257
|
+
const { listWorkflows } = await import('../../core/workflows/workflow-detector.js');
|
|
258
|
+
const validIds = listWorkflows().map(w => w.id).concat(['auto']);
|
|
259
|
+
if (!validIds.includes(value)) {
|
|
260
|
+
logger.error(`Invalid workflow: "${value}"`);
|
|
261
|
+
logger.dim(` Valid workflows: ${validIds.join(', ')}`);
|
|
262
|
+
logger.blank();
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
} catch {
|
|
266
|
+
// Workflow detector unavailable — skip validation
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
254
270
|
const spinner = ora('Updating state...').start();
|
|
255
271
|
|
|
256
272
|
// Parse value automatically (JSON, number, boolean)
|
|
@@ -401,7 +417,6 @@ async function markOutputCommand(featureName, outputType, options) {
|
|
|
401
417
|
logger.dim(' Valid types:');
|
|
402
418
|
logger.dim(' Proposal: proposal');
|
|
403
419
|
logger.dim(' Design: schemaAnalysis, spec, contracts, contractsVsa, decisions');
|
|
404
|
-
logger.dim(' Clarify: clarifications');
|
|
405
420
|
logger.dim(' Tasks: tasks');
|
|
406
421
|
logger.dim(' UI/UX: uiDesignSystem, uiMockups, uiComponents, uiFlows');
|
|
407
422
|
logger.dim(' Implement: recap');
|
|
@@ -52,7 +52,6 @@ export async function taskDoneCommand(featureName, taskIds, options) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
/**
|
|
56
55
|
/**
|
|
57
56
|
* Start task command
|
|
58
57
|
*/
|
|
@@ -66,23 +65,6 @@ export async function taskStartCommand(featureName, taskId, options) {
|
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
/**
|
|
70
|
-
* Bulk-start tasks command
|
|
71
|
-
*/
|
|
72
|
-
export async function taskBulkStartCommand(featureName, range, options) {
|
|
73
|
-
try {
|
|
74
|
-
const args = ['bulk-start', featureName];
|
|
75
|
-
if (range) args.push(range);
|
|
76
|
-
if (options.all) args.push('--all');
|
|
77
|
-
if (options.from) args.push('--from', options.from);
|
|
78
|
-
if (options.to) args.push('--to', options.to);
|
|
79
|
-
await executeTaskManager(args);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error(chalk.red(`Error: ${error.message}`));
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
68
|
/**
|
|
87
69
|
* Bulk-done tasks command
|
|
88
70
|
*/
|
|
@@ -118,15 +100,3 @@ export async function taskAnnotateCommand(featureName, taskId, text, options) {
|
|
|
118
100
|
}
|
|
119
101
|
}
|
|
120
102
|
|
|
121
|
-
/**
|
|
122
|
-
* Get next task command
|
|
123
|
-
*/
|
|
124
|
-
export async function taskNextCommand(featureName, options) {
|
|
125
|
-
try {
|
|
126
|
-
const args = ['next', featureName];
|
|
127
|
-
await executeTaskManager(args);
|
|
128
|
-
} catch (error) {
|
|
129
|
-
console.error(chalk.red(`Error: ${error.message}`));
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
@@ -51,10 +51,6 @@ const OUTPUT_SECTIONS = {
|
|
|
51
51
|
required: ['T001', 'category', 'dependencies'],
|
|
52
52
|
optional: ['CHECKPOINT', 'estimatedMinutes']
|
|
53
53
|
},
|
|
54
|
-
'clarifications.md': {
|
|
55
|
-
required: ['Q1', 'Answer', 'Edge Cases'],
|
|
56
|
-
optional: ['Assumptions', 'Business Rules']
|
|
57
|
-
}
|
|
58
54
|
};
|
|
59
55
|
|
|
60
56
|
/**
|
|
@@ -62,10 +58,8 @@ const OUTPUT_SECTIONS = {
|
|
|
62
58
|
*/
|
|
63
59
|
const PHASE_OUTPUTS = {
|
|
64
60
|
proposal: ['proposal.md'],
|
|
65
|
-
|
|
66
|
-
uiux: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'],
|
|
61
|
+
uiux: ['design-system.md', 'mockups.md', 'components.md', 'flows.md'],
|
|
67
62
|
design: ['spec.md', 'contracts.cs', 'schema-analysis.md', 'decisions.md'],
|
|
68
|
-
clarify: ['spec.md', 'clarifications.md'],
|
|
69
63
|
tasks: ['tasks.md'],
|
|
70
64
|
implement: ['spec.md', 'contracts.cs', 'tasks.md']
|
|
71
65
|
};
|
|
@@ -75,9 +69,8 @@ const PHASE_OUTPUTS = {
|
|
|
75
69
|
*/
|
|
76
70
|
const PHASE_FOLDERS = {
|
|
77
71
|
proposal: '0-proposal',
|
|
78
|
-
uiux: '
|
|
79
|
-
design: '
|
|
80
|
-
clarify: '1-design',
|
|
72
|
+
uiux: '1-ui',
|
|
73
|
+
design: '2-design',
|
|
81
74
|
plan: '3-plan',
|
|
82
75
|
tasks: '4-tasks',
|
|
83
76
|
implement: '5-implement',
|
|
@@ -17,26 +17,25 @@ import { join } from 'path';
|
|
|
17
17
|
*
|
|
18
18
|
* Fields:
|
|
19
19
|
* filename - The file's basename (e.g. 'spec.md')
|
|
20
|
-
* phaseDir - Subdirectory within .morph/features/{feature}/ (e.g. '
|
|
20
|
+
* phaseDir - Subdirectory within .morph/features/{feature}/ (e.g. '2-design')
|
|
21
21
|
* phase - The morph-spec phase that produces this output
|
|
22
22
|
* protected - Whether the file requires an approval gate before editing
|
|
23
23
|
* approvalGate - (optional) Which gate protects this file
|
|
24
24
|
*/
|
|
25
25
|
export const OUTPUT_SCHEMA = {
|
|
26
26
|
proposal: { filename: 'proposal.md', phaseDir: '0-proposal', phase: 'proposal', protected: false },
|
|
27
|
-
schemaAnalysis:{ filename: 'schema-analysis.md', phaseDir: '
|
|
28
|
-
spec: { filename: 'spec.md', phaseDir: '
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
contractsVsa: { filename: 'contracts-vsa.cs', phaseDir: '1-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
27
|
+
schemaAnalysis:{ filename: 'schema-analysis.md', phaseDir: '2-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
28
|
+
spec: { filename: 'spec.md', phaseDir: '2-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
29
|
+
contracts: { filename: 'contracts.cs', phaseDir: '2-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
30
|
+
contractsTs: { filename: 'contracts.ts', phaseDir: '2-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
31
|
+
contractsVsa: { filename: 'contracts-vsa.cs', phaseDir: '2-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
33
32
|
plan: { filename: 'plan.md', phaseDir: '3-plan', phase: 'plan', protected: true, approvalGate: 'plan' },
|
|
34
33
|
tasks: { filename: 'tasks.md', phaseDir: '4-tasks', phase: 'tasks', protected: true, approvalGate: 'tasks' },
|
|
35
|
-
uiDesignSystem:{ filename: 'design-system.md', phaseDir: '
|
|
36
|
-
uiMockups: { filename: 'mockups.md', phaseDir: '
|
|
37
|
-
uiComponents: { filename: 'components.md', phaseDir: '
|
|
38
|
-
uiFlows: { filename: 'flows.md', phaseDir: '
|
|
39
|
-
decisions: { filename: 'decisions.md', phaseDir: '
|
|
34
|
+
uiDesignSystem:{ filename: 'design-system.md', phaseDir: '1-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
35
|
+
uiMockups: { filename: 'mockups.md', phaseDir: '1-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
36
|
+
uiComponents: { filename: 'components.md', phaseDir: '1-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
37
|
+
uiFlows: { filename: 'flows.md', phaseDir: '1-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
38
|
+
decisions: { filename: 'decisions.md', phaseDir: '2-design', phase: 'design', protected: false },
|
|
40
39
|
recap: { filename: 'recap.md', phaseDir: '5-implement', phase: 'implement', protected: false },
|
|
41
40
|
};
|
|
42
41
|
|
|
@@ -50,7 +49,7 @@ export const OUTPUT_SCHEMA = {
|
|
|
50
49
|
*
|
|
51
50
|
* @param {string} featureName - The feature name
|
|
52
51
|
* @param {string} outputType - camelCase output type key from OUTPUT_SCHEMA
|
|
53
|
-
* @returns {string} e.g. ".morph/features/my-feature/
|
|
52
|
+
* @returns {string} e.g. ".morph/features/my-feature/2-design/spec.md"
|
|
54
53
|
*/
|
|
55
54
|
export function getOutputPath(featureName, outputType) {
|
|
56
55
|
const entry = OUTPUT_SCHEMA[outputType];
|