@polymorphism-tech/morph-spec 4.3.7 → 4.6.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 +6 -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/{standards → framework/standards}/frontend/nextjs/nextjs-patterns.md +17 -0
- 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/framework/templates/docs/user-stories.md +34 -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 +7 -0
- package/.morph/memory/pre-compact-2026-02-23T15-43-03-521Z.json +16 -0
- package/.morph/state.json +1 -1
- package/CLAUDE.md +77 -155
- 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/{skills/level-2-domains → agents}/ai-agents/ai-system-architect.md +7 -3
- package/framework/{skills/level-2-domains → agents}/architecture/po-pm-advisor.md +7 -1
- package/framework/{skills/level-2-domains → agents}/architecture/prompt-engineer.md +7 -1
- package/framework/{skills/level-2-domains → agents}/architecture/seo-growth-hacker.md +7 -1
- package/framework/{skills/level-2-domains → agents}/architecture/standards-architect.md +10 -6
- package/framework/agents/backend/api-designer.md +103 -0
- package/framework/{skills/level-2-domains → agents}/backend/dotnet-senior.md +7 -1
- package/framework/agents/backend/ef-modeler.md +119 -0
- package/framework/{skills/level-2-domains → agents}/backend/hangfire-orchestrator.md +8 -4
- package/framework/{skills/level-2-domains → agents}/backend/ms-agent-expert.md +7 -3
- package/framework/{skills/level-2-domains → agents}/frontend/blazor-builder.md +7 -3
- package/framework/{skills/level-2-domains → agents}/frontend/nextjs-expert.md +7 -3
- package/framework/{skills/level-2-domains → agents}/frontend/ui-ux-designer.md +8 -2
- package/framework/{skills/level-2-domains → agents}/infrastructure/azure-architect.md +7 -1
- package/framework/{skills/level-2-domains → agents}/infrastructure/azure-deploy-specialist.md +7 -1
- package/framework/{skills/level-2-domains → agents}/infrastructure/bicep-architect.md +7 -3
- package/framework/{skills/level-2-domains → agents}/infrastructure/container-specialist.md +7 -3
- package/framework/{skills/level-2-domains → agents}/infrastructure/devops-engineer.md +7 -3
- package/framework/{skills/level-2-domains → agents}/integrations/asaas-financial.md +7 -3
- package/framework/{skills/level-2-domains → agents}/integrations/azure-identity.md +7 -3
- package/framework/{skills/level-2-domains → agents}/integrations/clerk-auth.md +7 -3
- package/framework/{skills/level-2-domains/integrations/hangfire-orchestrator.md → agents/integrations/hangfire-integration.md} +7 -1
- package/framework/{skills/level-2-domains → agents}/integrations/resend-email.md +7 -3
- package/framework/{skills/level-2-domains → agents}/quality/code-analyzer.md +9 -5
- package/framework/{skills/level-2-domains → agents}/quality/testing-specialist.md +7 -3
- 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 +538 -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/README.md +66 -0
- package/framework/skills/level-0-meta/brainstorming/SKILL.md +135 -0
- package/framework/skills/level-0-meta/brainstorming/references/proposal-example.md +138 -0
- package/framework/skills/level-0-meta/{code-review.md → code-review/SKILL.md} +13 -4
- package/framework/skills/level-0-meta/code-review/references/review-example.md +164 -0
- package/framework/skills/level-0-meta/code-review/scripts/scan-csharp.mjs +121 -0
- package/framework/skills/level-0-meta/mcp-registry.json +207 -0
- package/framework/skills/level-0-meta/{morph-checklist.md → morph-checklist/SKILL.md} +8 -3
- package/framework/skills/{level-1-workflows/morph-replicate.md → level-0-meta/morph-replicate/SKILL.md} +13 -6
- package/framework/skills/level-0-meta/{simulation-checklist.md → simulation-checklist/SKILL.md} +9 -4
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +334 -0
- package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +147 -0
- package/framework/skills/level-0-meta/verification-before-completion/scripts/check-phase-outputs.mjs +110 -0
- package/framework/skills/level-1-workflows/{phase-clarify.md → phase-clarify/SKILL.md} +65 -4
- package/framework/skills/level-1-workflows/phase-clarify/references/clarifications-example.md +117 -0
- package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -0
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +303 -0
- package/framework/skills/level-1-workflows/phase-design/references/spec-example.md +253 -0
- package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -0
- package/framework/skills/level-1-workflows/phase-implement/references/recap-example.md +132 -0
- package/framework/skills/level-1-workflows/phase-setup/SKILL.md +171 -0
- package/framework/skills/level-1-workflows/{phase-tasks.md → phase-tasks/SKILL.md} +89 -7
- package/framework/skills/level-1-workflows/phase-tasks/references/tasks-example.md +231 -0
- package/framework/skills/level-1-workflows/phase-tasks/scripts/validate-tasks.mjs +112 -0
- package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -0
- 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 -136
- 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 +60 -88
- 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 +390 -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 +118 -0
- package/.morph/project/context/README.md +0 -17
- 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/framework/skills/level-1-workflows/phase-design.md +0 -213
- package/framework/skills/level-1-workflows/phase-setup.md +0 -106
- package/framework/skills/level-1-workflows/phase-uiux.md +0 -169
- package/framework/skills/level-2-domains/backend/api-designer.md +0 -59
- package/framework/skills/level-2-domains/backend/ef-modeler.md +0 -58
- package/framework/skills/level-3-technologies/README.md +0 -7
- package/framework/skills/level-4-patterns/README.md +0 -7
- 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/{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}/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/{skills/level-2-domains → agents}/README.md +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,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MORPH-SPEC Feature Validation Command
|
|
3
|
+
*
|
|
4
|
+
* Content-aware validation of feature outputs at each phase.
|
|
5
|
+
* Checks section presence, schema consistency, and contract correctness.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* morph-spec validate <feature-name> [--phase <phase>] [--json] [--verbose]
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* morph-spec validate user-portal --phase design
|
|
12
|
+
* morph-spec validate user-portal --json
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
import { getFeature } from '../../core/state/state-manager.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Expected sections per output file
|
|
22
|
+
*/
|
|
23
|
+
const OUTPUT_SECTIONS = {
|
|
24
|
+
'proposal.md': {
|
|
25
|
+
required: ['Overview', 'Problem', 'Solution', 'Scope'],
|
|
26
|
+
optional: ['Agents', 'Stack', 'Risks']
|
|
27
|
+
},
|
|
28
|
+
'spec.md': {
|
|
29
|
+
required: [
|
|
30
|
+
'Overview', 'Functional Requirements', 'Non-Functional Requirements',
|
|
31
|
+
'Technical Architecture', 'Data Model'
|
|
32
|
+
],
|
|
33
|
+
optional: [
|
|
34
|
+
'Infrastructure', 'Testing Strategy', 'Security',
|
|
35
|
+
'Performance', 'Edge Cases', 'Clarifications'
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
'contracts.cs': {
|
|
39
|
+
required: ['namespace', 'record', 'interface'],
|
|
40
|
+
isCode: true
|
|
41
|
+
},
|
|
42
|
+
'schema-analysis.md': {
|
|
43
|
+
required: ['Tables Analyzed', 'Columns', 'Relationships'],
|
|
44
|
+
optional: ['CRITICAL FINDINGS', 'Recommendations', 'Indexes']
|
|
45
|
+
},
|
|
46
|
+
'decisions.md': {
|
|
47
|
+
required: ['ADR', 'Status', 'Context', 'Decision'],
|
|
48
|
+
optional: ['Consequences', 'Alternatives', 'Costs']
|
|
49
|
+
},
|
|
50
|
+
'tasks.md': {
|
|
51
|
+
required: ['T001', 'category', 'dependencies'],
|
|
52
|
+
optional: ['CHECKPOINT', 'estimatedMinutes']
|
|
53
|
+
},
|
|
54
|
+
'clarifications.md': {
|
|
55
|
+
required: ['Q1', 'Answer', 'Edge Cases'],
|
|
56
|
+
optional: ['Assumptions', 'Business Rules']
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Phase-to-output mapping
|
|
62
|
+
*/
|
|
63
|
+
const PHASE_OUTPUTS = {
|
|
64
|
+
proposal: ['proposal.md'],
|
|
65
|
+
setup: ['proposal.md'],
|
|
66
|
+
uiux: ['ui-design-system.md', 'ui-mockups.md', 'ui-components.md', 'ui-flows.md'],
|
|
67
|
+
design: ['spec.md', 'contracts.cs', 'schema-analysis.md', 'decisions.md'],
|
|
68
|
+
clarify: ['spec.md', 'clarifications.md'],
|
|
69
|
+
tasks: ['tasks.md'],
|
|
70
|
+
implement: ['spec.md', 'contracts.cs', 'tasks.md']
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Validate a single output file
|
|
75
|
+
*/
|
|
76
|
+
function validateOutput(featurePath, outputFile) {
|
|
77
|
+
const filePath = path.join(featurePath, outputFile);
|
|
78
|
+
const result = {
|
|
79
|
+
file: outputFile,
|
|
80
|
+
exists: false,
|
|
81
|
+
sections: { found: [], missing: [], optional: [] },
|
|
82
|
+
warnings: [],
|
|
83
|
+
errors: [],
|
|
84
|
+
lineCount: 0
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
if (!fs.existsSync(filePath)) {
|
|
88
|
+
result.errors.push(`File not found: ${outputFile}`);
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
result.exists = true;
|
|
93
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
94
|
+
result.lineCount = content.split('\n').length;
|
|
95
|
+
|
|
96
|
+
// Skip section checks for files without defined sections
|
|
97
|
+
const sections = OUTPUT_SECTIONS[outputFile];
|
|
98
|
+
if (!sections) {
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (sections.isCode) {
|
|
103
|
+
// C# code validation
|
|
104
|
+
validateCSharpContent(content, result);
|
|
105
|
+
} else {
|
|
106
|
+
// Markdown section validation
|
|
107
|
+
validateMarkdownSections(content, sections, result);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Size warnings
|
|
111
|
+
if (result.lineCount < 10) {
|
|
112
|
+
result.warnings.push(`File is very short (${result.lineCount} lines) — may be incomplete`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Validate markdown sections
|
|
120
|
+
*/
|
|
121
|
+
function validateMarkdownSections(content, sections, result) {
|
|
122
|
+
const contentLower = content.toLowerCase();
|
|
123
|
+
|
|
124
|
+
for (const section of sections.required) {
|
|
125
|
+
if (contentLower.includes(section.toLowerCase())) {
|
|
126
|
+
result.sections.found.push(section);
|
|
127
|
+
} else {
|
|
128
|
+
result.sections.missing.push(section);
|
|
129
|
+
result.errors.push(`Missing required section: "${section}"`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
for (const section of (sections.optional || [])) {
|
|
134
|
+
if (contentLower.includes(section.toLowerCase())) {
|
|
135
|
+
result.sections.optional.push(section);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Validate C# contracts content
|
|
142
|
+
*/
|
|
143
|
+
function validateCSharpContent(content, result) {
|
|
144
|
+
// Check for namespace
|
|
145
|
+
if (/namespace\s+\S+/.test(content)) {
|
|
146
|
+
result.sections.found.push('namespace');
|
|
147
|
+
} else {
|
|
148
|
+
result.sections.missing.push('namespace');
|
|
149
|
+
result.errors.push('Missing namespace declaration');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check for records (DTOs)
|
|
153
|
+
const records = content.match(/public\s+record\s+\w+/g) || [];
|
|
154
|
+
if (records.length > 0) {
|
|
155
|
+
result.sections.found.push(`${records.length} record(s)`);
|
|
156
|
+
} else {
|
|
157
|
+
result.warnings.push('No record types found — DTOs expected');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Check for interfaces
|
|
161
|
+
const interfaces = content.match(/public\s+interface\s+I\w+/g) || [];
|
|
162
|
+
if (interfaces.length > 0) {
|
|
163
|
+
result.sections.found.push(`${interfaces.length} interface(s)`);
|
|
164
|
+
} else {
|
|
165
|
+
result.warnings.push('No interfaces found — service contracts expected');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Check for CancellationToken in async methods
|
|
169
|
+
const asyncMethods = content.match(/Task<.*>\s+\w+\(/g) || [];
|
|
170
|
+
const methodsWithCt = content.match(/CancellationToken\s+ct/g) || [];
|
|
171
|
+
if (asyncMethods.length > 0 && methodsWithCt.length < asyncMethods.length) {
|
|
172
|
+
result.warnings.push(
|
|
173
|
+
`${asyncMethods.length - methodsWithCt.length} async method(s) may be missing CancellationToken`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Check for schema-analysis reference
|
|
178
|
+
if (content.includes('schema-analysis')) {
|
|
179
|
+
result.sections.found.push('schema reference');
|
|
180
|
+
} else {
|
|
181
|
+
result.warnings.push('No reference to schema-analysis.md — fields may not match database');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Cross-validate contracts against schema-analysis
|
|
187
|
+
*/
|
|
188
|
+
function crossValidateSchema(featurePath) {
|
|
189
|
+
const schemaPath = path.join(featurePath, 'schema-analysis.md');
|
|
190
|
+
const contractsPath = path.join(featurePath, 'contracts.cs');
|
|
191
|
+
const warnings = [];
|
|
192
|
+
|
|
193
|
+
if (!fs.existsSync(schemaPath) || !fs.existsSync(contractsPath)) {
|
|
194
|
+
return warnings;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const schema = fs.readFileSync(schemaPath, 'utf8');
|
|
198
|
+
const contracts = fs.readFileSync(contractsPath, 'utf8');
|
|
199
|
+
|
|
200
|
+
// Extract field names from schema (look for column names in tables)
|
|
201
|
+
const schemaFields = new Set();
|
|
202
|
+
const columnRegex = /\|\s*(\w+)\s*\|/g;
|
|
203
|
+
let match;
|
|
204
|
+
while ((match = columnRegex.exec(schema)) !== null) {
|
|
205
|
+
const field = match[1].toLowerCase();
|
|
206
|
+
if (!['column', 'name', 'type', 'nullable', 'default', 'notes', 'table', '---'].includes(field)) {
|
|
207
|
+
schemaFields.add(field);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Extract field names from contracts
|
|
212
|
+
const contractFields = new Set();
|
|
213
|
+
const fieldRegex = /(?:string|int|Guid|DateTime|bool|decimal|JsonObject)\???\s+(\w+)/g;
|
|
214
|
+
while ((match = fieldRegex.exec(contracts)) !== null) {
|
|
215
|
+
contractFields.add(match[1].toLowerCase());
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check for contract fields not in schema
|
|
219
|
+
for (const field of contractFields) {
|
|
220
|
+
if (schemaFields.size > 0 && !schemaFields.has(field) && field !== 'ct') {
|
|
221
|
+
warnings.push(`Contract field "${field}" not found in schema-analysis.md — verify correctness`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return warnings;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Main validate command
|
|
230
|
+
*/
|
|
231
|
+
export async function validateFeatureCommand(featureName, options = {}) {
|
|
232
|
+
if (!featureName) {
|
|
233
|
+
console.error(chalk.red('Error: Feature name required'));
|
|
234
|
+
console.error(chalk.gray('Usage: morph-spec validate <feature-name> [--phase <phase>]'));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const featurePath = path.join(process.cwd(), '.morph/features', featureName);
|
|
239
|
+
|
|
240
|
+
if (!fs.existsSync(featurePath)) {
|
|
241
|
+
console.error(chalk.red(`Error: Feature directory not found: ${featurePath}`));
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Determine which outputs to validate
|
|
246
|
+
const phase = options.phase || null;
|
|
247
|
+
let outputFiles;
|
|
248
|
+
|
|
249
|
+
if (phase) {
|
|
250
|
+
outputFiles = PHASE_OUTPUTS[phase];
|
|
251
|
+
if (!outputFiles) {
|
|
252
|
+
console.error(chalk.red(`Unknown phase: ${phase}`));
|
|
253
|
+
console.error(chalk.gray(`Valid phases: ${Object.keys(PHASE_OUTPUTS).join(', ')}`));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
// Validate all existing outputs
|
|
258
|
+
outputFiles = fs.readdirSync(featurePath).filter(f => f.endsWith('.md') || f.endsWith('.cs'));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Run validation
|
|
262
|
+
const results = outputFiles.map(file => validateOutput(featurePath, file));
|
|
263
|
+
const schemaWarnings = crossValidateSchema(featurePath);
|
|
264
|
+
|
|
265
|
+
// Aggregate results
|
|
266
|
+
const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
|
|
267
|
+
const totalWarnings = results.reduce((sum, r) => sum + r.warnings.length, 0) + schemaWarnings.length;
|
|
268
|
+
const totalFound = results.reduce((sum, r) => sum + r.sections.found.length, 0);
|
|
269
|
+
|
|
270
|
+
// JSON output mode
|
|
271
|
+
if (options.json) {
|
|
272
|
+
const output = {
|
|
273
|
+
feature: featureName,
|
|
274
|
+
phase: phase || 'all',
|
|
275
|
+
valid: totalErrors === 0,
|
|
276
|
+
summary: {
|
|
277
|
+
files: results.length,
|
|
278
|
+
errors: totalErrors,
|
|
279
|
+
warnings: totalWarnings,
|
|
280
|
+
sectionsFound: totalFound
|
|
281
|
+
},
|
|
282
|
+
results: results.map(r => ({
|
|
283
|
+
file: r.file,
|
|
284
|
+
exists: r.exists,
|
|
285
|
+
lineCount: r.lineCount,
|
|
286
|
+
errors: r.errors,
|
|
287
|
+
warnings: r.warnings,
|
|
288
|
+
sectionsFound: r.sections.found,
|
|
289
|
+
sectionsMissing: r.sections.missing
|
|
290
|
+
})),
|
|
291
|
+
schemaWarnings
|
|
292
|
+
};
|
|
293
|
+
console.log(JSON.stringify(output, null, 2));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Visual output
|
|
298
|
+
console.log(chalk.cyan('\n┌────────────────────────────────────────────────────────────┐'));
|
|
299
|
+
console.log(chalk.cyan('│ MORPH-SPEC FEATURE VALIDATOR │'));
|
|
300
|
+
console.log(chalk.cyan('└────────────────────────────────────────────────────────────┘\n'));
|
|
301
|
+
|
|
302
|
+
console.log(chalk.white.bold(`Feature: ${featureName}`));
|
|
303
|
+
if (phase) console.log(chalk.gray(`Phase: ${phase}`));
|
|
304
|
+
console.log('');
|
|
305
|
+
|
|
306
|
+
// File-by-file results
|
|
307
|
+
for (const result of results) {
|
|
308
|
+
const symbol = result.exists
|
|
309
|
+
? (result.errors.length === 0 ? '✅' : '❌')
|
|
310
|
+
: '⬜';
|
|
311
|
+
const name = result.exists
|
|
312
|
+
? (result.errors.length === 0 ? chalk.green(result.file) : chalk.red(result.file))
|
|
313
|
+
: chalk.gray(result.file);
|
|
314
|
+
|
|
315
|
+
console.log(`${symbol} ${name}${result.exists ? chalk.gray(` (${result.lineCount} lines)`) : ''}`);
|
|
316
|
+
|
|
317
|
+
// Sections found
|
|
318
|
+
if (result.sections.found.length > 0 && (options.verbose || result.errors.length > 0)) {
|
|
319
|
+
result.sections.found.forEach(s => {
|
|
320
|
+
console.log(chalk.green(` ✓ ${s}`));
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Errors
|
|
325
|
+
result.errors.forEach(err => {
|
|
326
|
+
console.log(chalk.red(` ✗ ${err}`));
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// Warnings
|
|
330
|
+
result.warnings.forEach(warn => {
|
|
331
|
+
console.log(chalk.yellow(` ⚠ ${warn}`));
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Schema cross-validation
|
|
336
|
+
if (schemaWarnings.length > 0) {
|
|
337
|
+
console.log(chalk.yellow('\nSchema Cross-Validation:'));
|
|
338
|
+
schemaWarnings.forEach(w => {
|
|
339
|
+
console.log(chalk.yellow(` ⚠ ${w}`));
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Summary
|
|
344
|
+
console.log('');
|
|
345
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
346
|
+
|
|
347
|
+
if (totalErrors === 0) {
|
|
348
|
+
console.log(chalk.green(`\n✓ VALIDATION PASSED — ${results.filter(r => r.exists).length} files validated`));
|
|
349
|
+
if (totalWarnings > 0) {
|
|
350
|
+
console.log(chalk.yellow(` ${totalWarnings} warning(s) — review recommended`));
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
console.log(chalk.red(`\n✗ VALIDATION FAILED — ${totalErrors} error(s), ${totalWarnings} warning(s)`));
|
|
354
|
+
console.log(chalk.yellow(' Fix errors before advancing to the next phase'));
|
|
355
|
+
}
|
|
356
|
+
console.log('');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export default validateFeatureCommand;
|
package/src/core/orchestrator.js
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import { ProjectScanner } from '../scanner/project-scanner.js';
|
|
8
8
|
import { ContextSanitizer } from '../sanitizer/context-sanitizer.js';
|
|
9
|
-
import { LLMAnalyzer } from '../llm/analyzer.js';
|
|
10
9
|
import { ConfigGenerator } from '../generator/config-generator.js';
|
|
11
10
|
import { UserReview } from '../ui/user-review.js';
|
|
12
11
|
import { InteractiveWizard } from '../ui/interactive-wizard.js';
|
|
@@ -26,7 +25,6 @@ export class AutoContextOrchestrator {
|
|
|
26
25
|
constructor() {
|
|
27
26
|
this.scanner = new ProjectScanner();
|
|
28
27
|
this.sanitizer = new ContextSanitizer();
|
|
29
|
-
this.llmAnalyzer = new LLMAnalyzer();
|
|
30
28
|
this.configGenerator = new ConfigGenerator();
|
|
31
29
|
this.userReview = new UserReview();
|
|
32
30
|
this.wizard = new InteractiveWizard();
|
|
@@ -41,15 +39,11 @@ export class AutoContextOrchestrator {
|
|
|
41
39
|
* @param {string} cwd - Current working directory
|
|
42
40
|
* @param {Object} [options] - Orchestration options
|
|
43
41
|
* @param {boolean} [options.skipReview] - Skip user review (auto-approve)
|
|
44
|
-
* @param {boolean} [options.fallbackOnError] - Fallback to wizard on LLM error (default: true)
|
|
45
|
-
* @param {boolean} [options.wizardMode] - Force wizard mode (skip LLM)
|
|
46
42
|
* @returns {Promise<{success: boolean, configs: GeneratedConfigs|null}>}
|
|
47
43
|
*/
|
|
48
44
|
async execute(cwd, options = {}) {
|
|
49
45
|
const {
|
|
50
46
|
skipReview = false,
|
|
51
|
-
fallbackOnError = true,
|
|
52
|
-
wizardMode = false
|
|
53
47
|
} = options;
|
|
54
48
|
|
|
55
49
|
try {
|
|
@@ -57,38 +51,9 @@ export class AutoContextOrchestrator {
|
|
|
57
51
|
|
|
58
52
|
let projectConfig;
|
|
59
53
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
projectConfig = await this.wizard.run();
|
|
64
|
-
} else {
|
|
65
|
-
try {
|
|
66
|
-
// Step 1a: Scan project
|
|
67
|
-
console.log(chalk.dim(' [1/6] Scanning project directory...'));
|
|
68
|
-
const projectContext = await this.scanner.scan(cwd);
|
|
69
|
-
|
|
70
|
-
// Step 1b: Sanitize context
|
|
71
|
-
console.log(chalk.dim(' [2/6] Sanitizing context (removing secrets)...'));
|
|
72
|
-
const sanitizedContext = this.sanitizer.sanitize(projectContext);
|
|
73
|
-
|
|
74
|
-
// Step 1c: Analyze with LLM
|
|
75
|
-
console.log(chalk.dim(' [3/6] Analyzing with Claude Code LLM...'));
|
|
76
|
-
projectConfig = await this.llmAnalyzer.analyze(sanitizedContext);
|
|
77
|
-
|
|
78
|
-
console.log(chalk.green(' ✓ Auto-detection successful\n'));
|
|
79
|
-
} catch (error) {
|
|
80
|
-
// LLM failed
|
|
81
|
-
console.log(chalk.yellow(`\n ⚠️ Auto-detection failed: ${error.message}\n`));
|
|
82
|
-
|
|
83
|
-
if (!fallbackOnError) {
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Fallback to wizard
|
|
88
|
-
console.log(chalk.cyan(' Falling back to interactive wizard...\n'));
|
|
89
|
-
projectConfig = await this.wizard.run();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
54
|
+
// Use interactive wizard (LLM invocation not implemented; wizard provides all context)
|
|
55
|
+
console.log(chalk.yellow(' Using interactive wizard mode\n'));
|
|
56
|
+
projectConfig = await this.wizard.run();
|
|
92
57
|
|
|
93
58
|
// Step 2: Generate configs
|
|
94
59
|
console.log(chalk.dim(' [4/6] Generating configuration files...'));
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output Schema — Single Source of Truth
|
|
3
|
+
*
|
|
4
|
+
* ALL output type definitions live here. Edit ONLY this file to add, rename,
|
|
5
|
+
* or relocate output types. Derived constants and generated files (phase-utils.js)
|
|
6
|
+
* are automatically updated by: node scripts/generate-refs.js
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Schema Definition
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Complete schema for all 12 output types produced by morph-spec phases.
|
|
17
|
+
*
|
|
18
|
+
* Fields:
|
|
19
|
+
* filename - The file's basename (e.g. 'spec.md')
|
|
20
|
+
* phaseDir - Subdirectory within .morph/features/{feature}/ (e.g. '1-design')
|
|
21
|
+
* phase - The morph-spec phase that produces this output
|
|
22
|
+
* protected - Whether the file requires an approval gate before editing
|
|
23
|
+
* approvalGate - (optional) Which gate protects this file
|
|
24
|
+
*/
|
|
25
|
+
export const OUTPUT_SCHEMA = {
|
|
26
|
+
proposal: { filename: 'proposal.md', phaseDir: '0-proposal', phase: 'proposal', protected: false },
|
|
27
|
+
schemaAnalysis:{ filename: 'schema-analysis.md', phaseDir: '1-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
28
|
+
spec: { filename: 'spec.md', phaseDir: '1-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
29
|
+
clarifications:{ filename: 'clarifications.md', phaseDir: '1-design', phase: 'clarify', protected: false },
|
|
30
|
+
contracts: { filename: 'contracts.cs', phaseDir: '1-design', phase: 'design', protected: true, approvalGate: 'design' },
|
|
31
|
+
tasks: { filename: 'tasks.md', phaseDir: '3-tasks', phase: 'tasks', protected: true, approvalGate: 'tasks' },
|
|
32
|
+
uiDesignSystem:{ filename: 'design-system.md', phaseDir: '2-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
33
|
+
uiMockups: { filename: 'mockups.md', phaseDir: '2-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
34
|
+
uiComponents: { filename: 'components.md', phaseDir: '2-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
35
|
+
uiFlows: { filename: 'flows.md', phaseDir: '2-ui', phase: 'uiux', protected: true, approvalGate: 'uiux' },
|
|
36
|
+
decisions: { filename: 'decisions.md', phaseDir: '1-design', phase: 'design', protected: false },
|
|
37
|
+
recap: { filename: 'recap.md', phaseDir: '4-implement', phase: 'implement', protected: false },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Builder Functions (Windows-safe via path.join)
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the morph-relative path for a specific output type of a feature.
|
|
46
|
+
* Returns forward-slash paths suitable for state.json storage.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} featureName - The feature name
|
|
49
|
+
* @param {string} outputType - camelCase output type key from OUTPUT_SCHEMA
|
|
50
|
+
* @returns {string} e.g. ".morph/features/my-feature/1-design/spec.md"
|
|
51
|
+
*/
|
|
52
|
+
export function getOutputPath(featureName, outputType) {
|
|
53
|
+
const entry = OUTPUT_SCHEMA[outputType];
|
|
54
|
+
if (!entry) {
|
|
55
|
+
throw new Error(`Unknown output type: "${outputType}". Valid types: ${Object.keys(OUTPUT_SCHEMA).join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
// Use path.join for OS-safe construction, then normalise to forward slashes
|
|
58
|
+
return join('.morph', 'features', featureName, entry.phaseDir, entry.filename)
|
|
59
|
+
.replace(/\\/g, '/');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get the absolute filesystem path for a specific output type.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} projectRoot - Absolute project root (e.g. process.cwd())
|
|
66
|
+
* @param {string} featureName - The feature name
|
|
67
|
+
* @param {string} outputType - camelCase output type key from OUTPUT_SCHEMA
|
|
68
|
+
* @returns {string} Absolute path using OS path separator
|
|
69
|
+
*/
|
|
70
|
+
export function getAbsoluteOutputPath(projectRoot, featureName, outputType) {
|
|
71
|
+
const entry = OUTPUT_SCHEMA[outputType];
|
|
72
|
+
if (!entry) {
|
|
73
|
+
throw new Error(`Unknown output type: "${outputType}". Valid types: ${Object.keys(OUTPUT_SCHEMA).join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
return join(projectRoot, '.morph', 'features', featureName, entry.phaseDir, entry.filename);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get the feature base directory (morph-relative, forward slashes).
|
|
80
|
+
*
|
|
81
|
+
* @param {string} featureName
|
|
82
|
+
* @returns {string} e.g. ".morph/features/my-feature"
|
|
83
|
+
*/
|
|
84
|
+
export function getFeatureDir(featureName) {
|
|
85
|
+
return join('.morph', 'features', featureName).replace(/\\/g, '/');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get all output paths for a feature, ready for use in state.json `outputs` block.
|
|
90
|
+
* Returns an object shaped like the state.json outputs for a single feature.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} featureName
|
|
93
|
+
* @returns {Object} e.g. { proposal: { created: false, path: '...' }, ... }
|
|
94
|
+
*/
|
|
95
|
+
export function getAllOutputPaths(featureName) {
|
|
96
|
+
const outputs = {};
|
|
97
|
+
for (const [key] of Object.entries(OUTPUT_SCHEMA)) {
|
|
98
|
+
outputs[key] = {
|
|
99
|
+
created: false,
|
|
100
|
+
path: getOutputPath(featureName, key),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return outputs;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Derived Constants (for direct import without calling functions)
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Map filename → output type (camelCase)
|
|
112
|
+
* e.g. { 'spec.md': 'spec', 'contracts.cs': 'contracts', ... }
|
|
113
|
+
*/
|
|
114
|
+
export const FILENAME_TO_OUTPUT = Object.fromEntries(
|
|
115
|
+
Object.entries(OUTPUT_SCHEMA).map(([key, entry]) => [entry.filename, key])
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Map output type (camelCase) → phase that produces it
|
|
120
|
+
* e.g. { spec: 'design', tasks: 'tasks', ... }
|
|
121
|
+
*/
|
|
122
|
+
export const OUTPUT_PHASE_MAP = Object.fromEntries(
|
|
123
|
+
Object.entries(OUTPUT_SCHEMA).map(([key, entry]) => [key, entry.phase])
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Protected spec files and the approval gate that locks them.
|
|
128
|
+
* Only includes files where protected === true.
|
|
129
|
+
* e.g. { 'spec.md': 'design', 'tasks.md': 'tasks', ... }
|
|
130
|
+
*/
|
|
131
|
+
export const PROTECTED_SPEC_FILES = Object.fromEntries(
|
|
132
|
+
Object.entries(OUTPUT_SCHEMA)
|
|
133
|
+
.filter(([, entry]) => entry.protected && entry.approvalGate)
|
|
134
|
+
.map(([, entry]) => [entry.filename, entry.approvalGate])
|
|
135
|
+
);
|