@polymorphism-tech/morph-spec 4.7.2 → 4.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.morph/analytics/threads-log.jsonl +54 -5
- package/.morph/state.json +152 -2
- package/LICENSE +1 -2
- package/README.md +379 -414
- package/bin/morph-spec.js +57 -394
- package/bin/validate.js +2 -26
- package/claude-plugin.json +2 -2
- package/docs/ARCHITECTURE.md +43 -46
- package/docs/CHEATSHEET.md +203 -221
- package/docs/COMMAND-FLOWS.md +319 -289
- package/docs/QUICKSTART.md +2 -8
- package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +2 -0
- package/docs/plans/2026-02-22-claude-settings.md +2 -0
- package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +2 -0
- package/docs/plans/2026-02-22-morph-spec-next.md +2 -0
- package/docs/plans/2026-02-22-native-alignment-design.md +2 -0
- package/docs/plans/2026-02-22-native-alignment-impl.md +2 -0
- package/docs/plans/2026-02-22-native-enrichment-design.md +2 -0
- package/docs/plans/2026-02-22-native-enrichment.md +2 -0
- package/docs/plans/2026-02-23-ddd-architecture-refactor.md +2 -0
- package/docs/plans/2026-02-23-ddd-nextsteps.md +2 -0
- package/docs/plans/2026-02-23-infra-architect-refactor.md +2 -0
- package/docs/plans/2026-02-23-nextjs-code-review-design.md +2 -1
- package/docs/plans/2026-02-23-nextjs-code-review-impl.md +2 -0
- package/docs/plans/2026-02-23-nextjs-standards-design.md +2 -1
- package/docs/plans/2026-02-23-nextjs-standards-impl.md +2 -0
- package/docs/plans/2026-02-24-cli-radical-simplification.md +592 -0
- package/docs/plans/2026-02-24-framework-failure-points.md +125 -0
- package/docs/plans/2026-02-24-morph-init-design.md +337 -0
- package/docs/plans/2026-02-24-morph-init-impl.md +1269 -0
- package/docs/plans/2026-02-24-tutorial-command-design.md +71 -0
- package/docs/plans/2026-02-24-tutorial-command.md +298 -0
- package/framework/CLAUDE.md +1 -1
- package/framework/commands/morph-proposal.md +3 -3
- package/framework/hooks/README.md +2 -5
- package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
- package/framework/hooks/claude-code/statusline.py +6 -1
- package/framework/hooks/dev/check-sync-health.js +117 -0
- package/framework/hooks/dev/guard-version-numbers.js +57 -0
- package/framework/hooks/dev/sync-standards-registry.js +60 -0
- package/framework/hooks/dev/sync-template-registry.js +60 -0
- package/framework/hooks/dev/validate-skill-format.js +70 -0
- package/framework/hooks/dev/validate-standard-format.js +73 -0
- package/framework/hooks/shared/payload-utils.js +39 -0
- package/framework/hooks/shared/state-reader.js +25 -1
- package/framework/rules/morph-workflow.md +1 -1
- package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
- package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
- package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
- package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
- package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
- package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
- package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
- package/framework/templates/examples/design-system-examples.md +1 -1
- package/framework/templates/ui/FluentDesignTheme.cs +1 -1
- package/framework/templates/ui/MudTheme.cs +1 -1
- package/framework/templates/ui/design-system.css +1 -1
- package/package.json +4 -2
- package/scripts/bump-version.js +248 -0
- package/scripts/install-dev-hooks.js +138 -0
- package/src/commands/agents/index.js +1 -2
- package/src/commands/index.js +13 -16
- package/src/commands/project/doctor.js +100 -14
- package/src/commands/project/index.js +7 -10
- package/src/commands/project/init.js +398 -528
- package/src/commands/project/install-plugin-cmd.js +28 -0
- package/src/commands/project/setup-infra-cmd.js +12 -0
- package/src/commands/project/tutorial.js +115 -0
- package/src/commands/state/approve.js +213 -221
- package/src/commands/state/index.js +0 -1
- package/src/commands/state/state.js +337 -365
- package/src/commands/templates/index.js +0 -4
- package/src/commands/trust/trust.js +1 -93
- package/src/commands/utils/index.js +1 -5
- package/src/commands/validation/index.js +1 -5
- package/src/core/registry/command-registry.js +11 -285
- package/src/core/state/state-manager.js +5 -2
- package/src/lib/detectors/index.js +81 -87
- package/src/lib/detectors/structure-detector.js +275 -273
- package/src/lib/generators/recap-generator.js +232 -225
- package/src/scripts/global-install.js +34 -0
- package/src/scripts/install-plugin.js +126 -0
- package/src/scripts/setup-infra.js +203 -0
- package/src/utils/agents-installer.js +10 -1
- package/src/utils/hooks-installer.js +66 -3
- package/.morph/.morphversion +0 -5
- package/.morph/config/config.json +0 -8
- package/.morph/framework/agents.json +0 -1815
- package/.morph/framework/hooks/README.md +0 -205
- package/.morph/framework/hooks/claude-code/notification/approval-reminder.js +0 -54
- package/.morph/framework/hooks/claude-code/post-tool-use/dispatch.js +0 -83
- package/.morph/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +0 -42
- package/.morph/framework/hooks/claude-code/pre-compact/save-morph-context.js +0 -61
- package/.morph/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +0 -71
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -58
- package/.morph/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +0 -64
- package/.morph/framework/hooks/claude-code/session-start/inject-morph-context.js +0 -94
- package/.morph/framework/hooks/claude-code/statusline.py +0 -538
- package/.morph/framework/hooks/claude-code/statusline.sh +0 -7
- package/.morph/framework/hooks/claude-code/stop/validate-completion.js +0 -88
- package/.morph/framework/hooks/claude-code/user-prompt/enrich-prompt.js +0 -91
- package/.morph/framework/hooks/git/commit-msg/conventional-commits.sh +0 -33
- package/.morph/framework/hooks/git/pre-commit/agents.sh +0 -25
- package/.morph/framework/hooks/git/pre-commit/orchestrator.sh +0 -64
- package/.morph/framework/hooks/git/pre-commit/specs.sh +0 -50
- package/.morph/framework/hooks/git/pre-push/run-tests.sh +0 -44
- package/.morph/framework/hooks/shared/hook-response.js +0 -45
- package/.morph/framework/hooks/shared/phase-utils.js +0 -129
- package/.morph/framework/hooks/shared/state-reader.js +0 -138
- package/.morph/framework/hooks/shared/stdin-reader.js +0 -26
- package/.morph/framework/standards/STANDARDS.json +0 -933
- package/.morph/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/.morph/framework/standards/ai-agents/production.md +0 -415
- package/.morph/framework/standards/ai-agents/setup.md +0 -418
- package/.morph/framework/standards/ai-agents/team-orchestration.md +0 -479
- package/.morph/framework/standards/ai-agents/workflows.md +0 -354
- package/.morph/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/.morph/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
- package/.morph/framework/standards/architecture/ddd/complexity-levels.md +0 -108
- package/.morph/framework/standards/architecture/ddd/entities.md +0 -99
- package/.morph/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
- package/.morph/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/.morph/framework/standards/backend/api/minimal-api.md +0 -494
- package/.morph/framework/standards/backend/api/rest.md +0 -492
- package/.morph/framework/standards/backend/api/validation.md +0 -88
- package/.morph/framework/standards/backend/authentication/passkeys.md +0 -428
- package/.morph/framework/standards/backend/database/ef-core.md +0 -199
- package/.morph/framework/standards/backend/database/migrations.md +0 -393
- package/.morph/framework/standards/backend/database/postgresql/database.md +0 -352
- package/.morph/framework/standards/backend/database/repository-patterns.md +0 -528
- package/.morph/framework/standards/backend/database/vector-search-rag.md +0 -541
- package/.morph/framework/standards/backend/dotnet/async.md +0 -366
- package/.morph/framework/standards/backend/dotnet/core.md +0 -117
- package/.morph/framework/standards/backend/dotnet/di.md +0 -439
- package/.morph/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/.morph/framework/standards/backend/integrations/asaas/asaas-api.md +0 -216
- package/.morph/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
- package/.morph/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +0 -350
- package/.morph/framework/standards/backend/integrations/resend/resend-email.md +0 -385
- package/.morph/framework/standards/context/analytics.md +0 -96
- package/.morph/framework/standards/context/bundles.md +0 -110
- package/.morph/framework/standards/context/priming.md +0 -78
- package/.morph/framework/standards/core/architecture.md +0 -185
- package/.morph/framework/standards/core/coding.md +0 -214
- package/.morph/framework/standards/core/git-branching-strategy.md +0 -403
- package/.morph/framework/standards/core/git.md +0 -185
- package/.morph/framework/standards/core/testing.md +0 -295
- package/.morph/framework/standards/data/nosql/blob-storage.md +0 -102
- package/.morph/framework/standards/data/nosql/cache/redis.md +0 -97
- package/.morph/framework/standards/data/nosql/cosmos-db.md +0 -118
- package/.morph/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/.morph/framework/standards/data/vector-search/rag-chunking.md +0 -104
- package/.morph/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/.morph/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/.morph/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/.morph/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/.morph/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/.morph/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/.morph/framework/standards/frontend/blazor/state.md +0 -191
- package/.morph/framework/standards/frontend/design-system/animations.md +0 -151
- package/.morph/framework/standards/frontend/design-system/naming.md +0 -64
- package/.morph/framework/standards/frontend/nextjs/app-router.md +0 -123
- package/.morph/framework/standards/frontend/nextjs/components.md +0 -132
- package/.morph/framework/standards/frontend/nextjs/data-fetching.md +0 -126
- package/.morph/framework/standards/frontend/nextjs/forms.md +0 -128
- package/.morph/framework/standards/frontend/nextjs/naming-conventions.md +0 -67
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +0 -215
- package/.morph/framework/standards/frontend/nextjs/project-structure.md +0 -102
- package/.morph/framework/standards/frontend/nextjs/state-management.md +0 -72
- package/.morph/framework/standards/frontend/nextjs/testing.md +0 -111
- package/.morph/framework/standards/infrastructure/azure/azure.md +0 -624
- package/.morph/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/.morph/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/.morph/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/.morph/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/.morph/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/.morph/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/.morph/framework/standards/infrastructure/docker/easypanel-deploy.md +0 -196
- package/.morph/framework/standards/infrastructure/supabase/mcp-setup.md +0 -252
- package/.morph/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
- package/.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
- package/.morph/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
- package/.morph/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
- package/.morph/framework/standards/integration/api/graphql.md +0 -91
- package/.morph/framework/standards/integration/api/grpc.md +0 -114
- package/.morph/framework/standards/integration/api/rest-design.md +0 -95
- package/.morph/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/.morph/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/.morph/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/.morph/framework/standards/integration/mcp/mcp-tools.md +0 -384
- package/.morph/framework/standards/observability/logging.md +0 -131
- package/.morph/framework/standards/observability/metrics.md +0 -121
- package/.morph/framework/standards/observability/monitoring.md +0 -114
- package/.morph/framework/standards/observability/tracing.md +0 -132
- package/.morph/framework/standards/workflows/parallel-execution.md +0 -112
- package/.morph/framework/standards/workflows/thread-management.md +0 -113
- package/.morph/framework/templates/.idea/morph-templates.xml +0 -92
- package/.morph/framework/templates/.vscode/morph-templates.code-snippets +0 -186
- package/.morph/framework/templates/IDE-SNIPPETS.md +0 -266
- package/.morph/framework/templates/README.md +0 -814
- package/.morph/framework/templates/REGISTRY.json +0 -1888
- package/.morph/framework/templates/code/dotnet/backend/repository.cs +0 -141
- package/.morph/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/.morph/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/.morph/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/README.md +0 -74
- package/.morph/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
- package/.morph/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
- package/.morph/framework/templates/code/dotnet/database/migration.cs +0 -83
- package/.morph/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/.morph/framework/templates/code/dotnet/jobs/agent.cs +0 -163
- package/.morph/framework/templates/code/dotnet/jobs/job.cs +0 -171
- package/.morph/framework/templates/code/dotnet/test.cs +0 -239
- package/.morph/framework/templates/code/sql/rls-policy.sql +0 -57
- package/.morph/framework/templates/code/sql/supabase-migration.sql +0 -100
- package/.morph/framework/templates/code/sql/supabase-migration.template.sql +0 -113
- package/.morph/framework/templates/code/typescript/contracts.ts +0 -168
- package/.morph/framework/templates/context/CONTEXT-FEATURE.md +0 -276
- package/.morph/framework/templates/context/CONTEXT.md +0 -181
- package/.morph/framework/templates/docs/clarifications.md +0 -253
- package/.morph/framework/templates/docs/onboarding.md +0 -123
- package/.morph/framework/templates/docs/proposal.md +0 -182
- package/.morph/framework/templates/docs/schema-analysis.md +0 -119
- package/.morph/framework/templates/docs/spec.md +0 -198
- package/.morph/framework/templates/docs/ui-components.md +0 -124
- package/.morph/framework/templates/docs/ui-design-system.md +0 -76
- package/.morph/framework/templates/docs/ui-flows.md +0 -167
- package/.morph/framework/templates/docs/ui-mockups.md +0 -98
- package/.morph/framework/templates/docs/user-stories.md +0 -34
- package/.morph/framework/templates/examples/design-system-examples.md +0 -357
- package/.morph/framework/templates/examples/spec-examples.md +0 -90
- package/.morph/framework/templates/feature/decisions.md +0 -187
- package/.morph/framework/templates/feature/recap.md +0 -146
- package/.morph/framework/templates/feature/tasks.md +0 -199
- package/.morph/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +0 -43
- package/.morph/framework/templates/frontend/nextjs/client-component.tsx.hbs +0 -26
- package/.morph/framework/templates/frontend/nextjs/env.mjs.hbs +0 -32
- package/.morph/framework/templates/frontend/nextjs/feature-form.tsx.hbs +0 -56
- package/.morph/framework/templates/frontend/nextjs/page.tsx.hbs +0 -22
- package/.morph/framework/templates/frontend/nextjs/tsconfig.json.hbs +0 -26
- package/.morph/framework/templates/frontend/nextjs/use-feature.ts.hbs +0 -54
- package/.morph/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/.morph/framework/templates/infrastructure/azure/README.md +0 -286
- package/.morph/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/.morph/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/.morph/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/.morph/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/.morph/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/.morph/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/.morph/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/.morph/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/.morph/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/.morph/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/.morph/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/.morph/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/.morph/framework/templates/infrastructure/docker/Dockerfile.template +0 -58
- package/.morph/framework/templates/infrastructure/docker/docker-compose.template.yml +0 -67
- package/.morph/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +0 -38
- package/.morph/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +0 -48
- package/.morph/framework/templates/infrastructure/docker/easypanel.template.json +0 -54
- package/.morph/framework/templates/infrastructure/github/README.md +0 -593
- package/.morph/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/.morph/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +0 -45
- package/.morph/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +0 -27
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/.morph/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
- package/.morph/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +0 -59
- package/.morph/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +0 -39
- package/.morph/framework/templates/integrations/asaas-client.cs +0 -387
- package/.morph/framework/templates/integrations/asaas-webhook.cs +0 -351
- package/.morph/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/.morph/framework/templates/integrations/clerk-config.cs +0 -258
- package/.morph/framework/templates/meta-prompts/fusion/fusion-agent.md +0 -76
- package/.morph/framework/templates/meta-prompts/fusion/fusion-aggregator.md +0 -100
- package/.morph/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
- package/.morph/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
- package/.morph/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-coordinator.md +0 -113
- package/.morph/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +0 -80
- package/.morph/framework/templates/meta-prompts/squad-leaders/backend-squad.md +0 -90
- package/.morph/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +0 -126
- package/.morph/framework/templates/meta-prompts/squad-leaders/squad-leader.md +0 -43
- package/.morph/framework/templates/meta-prompts/validators/checkpoint-validator.md +0 -107
- package/.morph/framework/templates/meta-prompts/validators/pre-commit-validator.md +0 -95
- package/.morph/framework/templates/project-structure/dotnet-ddd.md +0 -70
- package/.morph/framework/templates/saas/subscription.cs +0 -347
- package/.morph/framework/templates/saas/tenant.cs +0 -338
- package/.morph/framework/templates/state.template.json +0 -17
- package/.morph/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/.morph/framework/templates/ui/MudTheme.cs +0 -281
- package/.morph/framework/templates/ui/design-system.css +0 -226
- package/.morph/logs/tool-failures.log +0 -17
- package/.morph/memory/pre-compact-2026-02-24T17-43-30-049Z.json +0 -16
- package/.morph/plans/eager-watching-bunny.md +0 -105
- package/.morph/plans/temporal-seeking-nebula.md +0 -45
- package/CLAUDE.md +0 -77
- package/docs/claude-alignment-report.md +0 -137
- package/docs/examples/order-management/contracts.cs +0 -84
- package/docs/examples/order-management/proposal.md +0 -24
- package/docs/examples/order-management/spec.md +0 -162
- package/src/commands/feature/create-story.js +0 -362
- package/src/commands/feature/index.js +0 -6
- package/src/commands/feature/shard-spec.js +0 -225
- package/src/commands/feature/sprint-status.js +0 -250
- package/src/commands/generation/generate-onboarding.js +0 -169
- package/src/commands/generation/generate.js +0 -276
- package/src/commands/generation/index.js +0 -5
- package/src/commands/learning/capture-pattern.js +0 -121
- package/src/commands/learning/index.js +0 -5
- package/src/commands/learning/search-patterns.js +0 -126
- package/src/commands/mcp/mcp.js +0 -102
- package/src/commands/project/changes.js +0 -66
- package/src/commands/project/cost.js +0 -179
- package/src/commands/project/diff.js +0 -278
- package/src/commands/project/revert.js +0 -173
- package/src/commands/project/standards.js +0 -80
- package/src/commands/project/sync.js +0 -167
- package/src/commands/project/update-agents.js +0 -23
- package/src/commands/state/rollback-phase.js +0 -185
- package/src/commands/templates/template-customize.js +0 -87
- package/src/commands/templates/template-list.js +0 -114
- package/src/commands/templates/template-show.js +0 -129
- package/src/commands/templates/template-validate.js +0 -91
- package/src/commands/utils/troubleshoot.js +0 -222
- package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
- package/src/commands/validation/lint-fluent.js +0 -352
- package/src/commands/validation/validate-blazor-state.js +0 -210
- package/src/commands/validation/validate-blazor.js +0 -156
- package/src/commands/validation/validate-css.js +0 -84
- package/src/lib/detectors/conversation-analyzer.js +0 -163
- package/src/lib/learning/index.js +0 -7
- package/src/lib/learning/learning-system.js +0 -520
- package/src/lib/troubleshooting/index.js +0 -8
- package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
- package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
- package/src/llm/environment-detector.js +0 -43
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Design: `morph-spec tutorial` Command
|
|
2
|
+
|
|
3
|
+
**Status:** COMPLETE (see implementation plan)
|
|
4
|
+
|
|
5
|
+
**Date:** 2026-02-24
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
|
|
11
|
+
After `morph-spec init`, first-time users see a suggestion to run `morph-spec tutorial`, but the command doesn't exist. New users also lack a quick way to understand the spec-first workflow and its phase pipeline.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Goal
|
|
16
|
+
|
|
17
|
+
A self-contained CLI command that teaches the MORPH-SPEC mental model: the phase pipeline, what each phase produces, and how to trigger each phase. Pure stdout, no side effects.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Approach: Workflow Walkthrough
|
|
22
|
+
|
|
23
|
+
A static, colored terminal output that explains the full pipeline top-to-bottom. No arguments, no options, no network calls, no file I/O.
|
|
24
|
+
|
|
25
|
+
Chosen over:
|
|
26
|
+
- **Interactive mode** — risks accidentally modifying project state
|
|
27
|
+
- **Quick reference** — duplicates `--help` with little added value
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Output Structure
|
|
32
|
+
|
|
33
|
+
1. **Header** — title + one-sentence philosophy
|
|
34
|
+
2. **Pipeline diagram** — ASCII showing phase sequence with optional phases bracketed
|
|
35
|
+
3. **Per-phase block** — for each of the 8 phases:
|
|
36
|
+
- Phase name + number
|
|
37
|
+
- What it does (1 sentence)
|
|
38
|
+
- What it produces (output files)
|
|
39
|
+
- How to trigger it (CLI command or `/slash-command` in Claude Code)
|
|
40
|
+
4. **Getting Started** — 3-step CTA ending with `morph-spec doctor` tip
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Implementation
|
|
45
|
+
|
|
46
|
+
| Item | Detail |
|
|
47
|
+
|------|--------|
|
|
48
|
+
| File | `src/commands/project/tutorial.js` |
|
|
49
|
+
| Export | `tutorialCommand` |
|
|
50
|
+
| Registration (index) | `src/commands/project/index.js` |
|
|
51
|
+
| Registration (bin) | `bin/morph-spec.js` |
|
|
52
|
+
| Dependencies | `chalk` (already installed) |
|
|
53
|
+
| Side effects | None — pure stdout |
|
|
54
|
+
| Size | ~100 lines |
|
|
55
|
+
|
|
56
|
+
Also: revert `init.js:518` back to `morph-spec tutorial` (the original intent).
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Phases Covered
|
|
61
|
+
|
|
62
|
+
| Phase | Trigger |
|
|
63
|
+
|-------|---------|
|
|
64
|
+
| 0 · Proposal | `/morph-proposal <feature>` |
|
|
65
|
+
| 1 · Setup | auto-triggered inside `/morph-proposal` |
|
|
66
|
+
| 1.5 · UI/UX (optional) | `/phase-uiux <feature>` |
|
|
67
|
+
| 2 · Design | `/phase-design <feature>` |
|
|
68
|
+
| 3 · Clarify | `/phase-clarify <feature>` |
|
|
69
|
+
| 4 · Tasks | auto-generated, or `/phase-tasks <feature>` |
|
|
70
|
+
| 5 · Implement | `/morph-apply <feature>` |
|
|
71
|
+
| 6 · Sync (optional) | `morph-spec sync <feature>` |
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Tutorial Command Implementation Plan
|
|
2
|
+
|
|
3
|
+
**Status:** COMPLETE
|
|
4
|
+
|
|
5
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
6
|
+
|
|
7
|
+
**Goal:** Add a `morph-spec tutorial` command that prints the full MORPH-SPEC phase pipeline and getting-started steps to stdout.
|
|
8
|
+
|
|
9
|
+
**Architecture:** Single new file `src/commands/project/tutorial.js` exporting `tutorialCommand`. Registered in `bin/morph-spec.js` and re-exported from `src/commands/project/index.js`. Pure stdout using `chalk` — no file I/O, no network, no side effects. Also reverts `init.js` to suggest `morph-spec tutorial` (instead of the broken replacement made in a prior session).
|
|
10
|
+
|
|
11
|
+
**Tech Stack:** Node.js ESM, chalk (already installed), node:test + node:assert for tests.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### Task 1: Create `tutorial.js`
|
|
16
|
+
|
|
17
|
+
**Files:**
|
|
18
|
+
- Create: `src/commands/project/tutorial.js`
|
|
19
|
+
- Test: `test/commands/tutorial.test.js`
|
|
20
|
+
|
|
21
|
+
**Step 1: Write the failing test**
|
|
22
|
+
|
|
23
|
+
Create `test/commands/tutorial.test.js`:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import { test, describe } from 'node:test';
|
|
27
|
+
import assert from 'node:assert/strict';
|
|
28
|
+
import { tutorialCommand } from '../../src/commands/project/tutorial.js';
|
|
29
|
+
|
|
30
|
+
describe('tutorialCommand', () => {
|
|
31
|
+
test('tutorialCommand is a function', () => {
|
|
32
|
+
assert.equal(typeof tutorialCommand, 'function');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('tutorialCommand runs without throwing', () => {
|
|
36
|
+
assert.doesNotThrow(() => tutorialCommand());
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('tutorialCommand returns undefined (pure side-effect)', () => {
|
|
40
|
+
const result = tutorialCommand();
|
|
41
|
+
assert.equal(result, undefined);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Step 2: Run test to verify it fails**
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
node --test test/commands/tutorial.test.js
|
|
50
|
+
```
|
|
51
|
+
Expected: FAIL — "Cannot find module"
|
|
52
|
+
|
|
53
|
+
**Step 3: Write the implementation**
|
|
54
|
+
|
|
55
|
+
Create `src/commands/project/tutorial.js`:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
/**
|
|
59
|
+
* Tutorial Command
|
|
60
|
+
*
|
|
61
|
+
* Prints the MORPH-SPEC workflow pipeline and getting-started steps.
|
|
62
|
+
* Pure stdout — no file I/O, no network, no side effects.
|
|
63
|
+
*
|
|
64
|
+
* Usage: morph-spec tutorial
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
import chalk from 'chalk';
|
|
68
|
+
|
|
69
|
+
const PHASES = [
|
|
70
|
+
{
|
|
71
|
+
label: 'FASE 0 · PROPOSAL',
|
|
72
|
+
what: 'Captures user story + acceptance criteria.',
|
|
73
|
+
produces: '0-proposal/proposal.md',
|
|
74
|
+
how: '/morph-proposal <feature> (in Claude Code)',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: 'FASE 1 · SETUP',
|
|
78
|
+
what: 'Detects stack, activates agents, confirms environment.',
|
|
79
|
+
produces: '.morph/state.json initialized',
|
|
80
|
+
how: 'auto-triggered inside /morph-proposal',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: 'FASE 1.5 · UI/UX',
|
|
84
|
+
what: 'Design system, mockups, component specs, user flows.',
|
|
85
|
+
produces: '2-ui/{design-system,mockups,components,flows}.md',
|
|
86
|
+
how: '/phase-uiux <feature> (in Claude Code)',
|
|
87
|
+
optional: true,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: 'FASE 2 · DESIGN',
|
|
91
|
+
what: 'Technical spec + C# contracts + architecture decisions.',
|
|
92
|
+
produces: '1-design/{spec.md, contracts-level{N}.cs, decisions.md}',
|
|
93
|
+
how: '/phase-design <feature> (in Claude Code)',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
label: 'FASE 3 · CLARIFY',
|
|
97
|
+
what: 'Reviews spec for ambiguities, adds edge cases.',
|
|
98
|
+
produces: '1-design/spec.md (updated with clarifications)',
|
|
99
|
+
how: '/phase-clarify <feature> (in Claude Code)',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: 'FASE 4 · TASKS',
|
|
103
|
+
what: 'Atomic task breakdown, DDD-aware.',
|
|
104
|
+
produces: '3-tasks/tasks.md',
|
|
105
|
+
how: 'auto-generated during /morph-proposal, or /phase-tasks <feature>',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
label: 'FASE 5 · IMPLEMENT',
|
|
109
|
+
what: 'Code implementation with checkpoints every 3 tasks.',
|
|
110
|
+
produces: '4-implement/recap.md + source code',
|
|
111
|
+
how: '/morph-apply <feature> (in Claude Code)',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
label: 'FASE 6 · SYNC',
|
|
115
|
+
what: 'Syncs decisions back to project standards.',
|
|
116
|
+
produces: '.morph/framework/standards/ (updated)',
|
|
117
|
+
how: 'morph-spec sync <feature>',
|
|
118
|
+
optional: true,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const SEP = chalk.dim('─'.repeat(58));
|
|
123
|
+
|
|
124
|
+
export function tutorialCommand() {
|
|
125
|
+
console.log('');
|
|
126
|
+
console.log(chalk.cyan.bold(' MORPH-SPEC Workflow Tutorial'));
|
|
127
|
+
console.log(SEP);
|
|
128
|
+
console.log('');
|
|
129
|
+
console.log(
|
|
130
|
+
chalk.white(
|
|
131
|
+
' MORPH-SPEC is spec-first: every feature goes through phases\n' +
|
|
132
|
+
' before any code is written. Each phase produces structured\n' +
|
|
133
|
+
' outputs that feed the next.'
|
|
134
|
+
)
|
|
135
|
+
);
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(SEP);
|
|
138
|
+
console.log(chalk.cyan.bold(' PIPELINE'));
|
|
139
|
+
console.log(SEP);
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(
|
|
142
|
+
chalk.white(' proposal → setup → ') +
|
|
143
|
+
chalk.dim('[uiux]') +
|
|
144
|
+
chalk.white(' → design → clarify → tasks → implement → ') +
|
|
145
|
+
chalk.dim('[sync]')
|
|
146
|
+
);
|
|
147
|
+
console.log(chalk.dim(' (phases in brackets are optional)'));
|
|
148
|
+
console.log('');
|
|
149
|
+
|
|
150
|
+
for (const phase of PHASES) {
|
|
151
|
+
console.log(SEP);
|
|
152
|
+
const label = phase.optional
|
|
153
|
+
? chalk.cyan.bold(` ${phase.label}`) + chalk.dim(' [optional]')
|
|
154
|
+
: chalk.cyan.bold(` ${phase.label}`);
|
|
155
|
+
console.log(label);
|
|
156
|
+
console.log(chalk.white(` What: ${phase.what}`));
|
|
157
|
+
console.log(chalk.dim(` Produces: ${phase.produces}`));
|
|
158
|
+
console.log(chalk.green(` How: ${phase.how}`));
|
|
159
|
+
console.log('');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(SEP);
|
|
163
|
+
console.log(chalk.cyan.bold(' GETTING STARTED'));
|
|
164
|
+
console.log(SEP);
|
|
165
|
+
console.log('');
|
|
166
|
+
console.log(chalk.white(' 1. Open Claude Code in your project'));
|
|
167
|
+
console.log(chalk.white(' 2. Run: ') + chalk.green('/morph-proposal <your-feature-name>'));
|
|
168
|
+
console.log(chalk.white(' 3. Answer the questions — morph-spec handles the rest'));
|
|
169
|
+
console.log('');
|
|
170
|
+
console.log(chalk.dim(' Tip: run `morph-spec doctor` to verify your installation first.'));
|
|
171
|
+
console.log('');
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**Step 4: Run test to verify it passes**
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
node --test test/commands/tutorial.test.js
|
|
179
|
+
```
|
|
180
|
+
Expected: 3 passing
|
|
181
|
+
|
|
182
|
+
**Step 5: Commit**
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
git add src/commands/project/tutorial.js test/commands/tutorial.test.js
|
|
186
|
+
git commit -m "feat(tutorial): add tutorial command with phase pipeline walkthrough"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### Task 2: Wire into project index and bin
|
|
192
|
+
|
|
193
|
+
**Files:**
|
|
194
|
+
- Modify: `src/commands/project/index.js`
|
|
195
|
+
- Modify: `bin/morph-spec.js`
|
|
196
|
+
|
|
197
|
+
**Step 1: Add export to `src/commands/project/index.js`**
|
|
198
|
+
|
|
199
|
+
After the existing `export { updateCommand }` line, add:
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
export { tutorialCommand } from './tutorial.js';
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Step 2: Add import to `bin/morph-spec.js`**
|
|
206
|
+
|
|
207
|
+
After the `import { doctorCommand }` line (line ~13), add:
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
import { tutorialCommand } from '../src/commands/project/tutorial.js';
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Step 3: Register the command in `bin/morph-spec.js`**
|
|
214
|
+
|
|
215
|
+
After the `doctor` command block (~line 128), add:
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
program
|
|
219
|
+
.command('tutorial')
|
|
220
|
+
.description('Learn the MORPH-SPEC workflow — phase pipeline and getting started')
|
|
221
|
+
.action(tutorialCommand);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Step 4: Smoke-test the CLI**
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
node bin/morph-spec.js tutorial
|
|
228
|
+
```
|
|
229
|
+
Expected: Full pipeline output printed to terminal without errors.
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
node bin/morph-spec.js --help | grep tutorial
|
|
233
|
+
```
|
|
234
|
+
Expected: `tutorial Learn the MORPH-SPEC workflow...`
|
|
235
|
+
|
|
236
|
+
**Step 5: Commit**
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
git add src/commands/project/index.js bin/morph-spec.js
|
|
240
|
+
git commit -m "feat(tutorial): register tutorial command in CLI"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### Task 3: Restore the `init.js` suggestion message
|
|
246
|
+
|
|
247
|
+
**Files:**
|
|
248
|
+
- Modify: `src/commands/project/init.js:518`
|
|
249
|
+
|
|
250
|
+
**Step 1: Revert the message**
|
|
251
|
+
|
|
252
|
+
Find line 518 in `src/commands/project/init.js`. Replace:
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
logger.info('First time using morph-spec? Run `morph-spec doctor` to verify your setup, then `/morph-proposal <feature>` to start.');
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
With:
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
logger.info('First time using morph-spec? Run `morph-spec tutorial` to get started.');
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Step 2: Verify the change**
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
grep -n "tutorial" src/commands/project/init.js
|
|
268
|
+
```
|
|
269
|
+
Expected: line 518 shows `morph-spec tutorial`
|
|
270
|
+
|
|
271
|
+
**Step 3: Commit**
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
git add src/commands/project/init.js
|
|
275
|
+
git commit -m "fix(init): restore morph-spec tutorial suggestion after command now exists"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### Task 4: Run full test suite
|
|
281
|
+
|
|
282
|
+
**Step 1: Run all tests**
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
node --test
|
|
286
|
+
```
|
|
287
|
+
Expected: all existing tests pass + 3 new tutorial tests pass, 0 failures.
|
|
288
|
+
|
|
289
|
+
**Step 2: If any failures, fix before continuing**
|
|
290
|
+
|
|
291
|
+
Do not proceed until `node --test` shows 0 failures.
|
|
292
|
+
|
|
293
|
+
**Step 3: Commit if any fixes were needed**
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
git add -p
|
|
297
|
+
git commit -m "fix(tutorial): address test suite issues"
|
|
298
|
+
```
|
package/framework/CLAUDE.md
CHANGED
|
@@ -22,9 +22,9 @@ npx morph-spec state get {feature-name}
|
|
|
22
22
|
### Workflow
|
|
23
23
|
|
|
24
24
|
1. **Detecte agentes automaticamente:**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
- Read `.morph/framework/agents.json`
|
|
26
|
+
- Para cada agente, compare `domains` e `keywords` com a feature solicitada
|
|
27
|
+
- Registre os agentes relevantes: `npx morph-spec state add-agent {feature-name} {agent-id}`
|
|
28
28
|
|
|
29
29
|
2. **Invoque skills dos agentes detectados:**
|
|
30
30
|
- Para agentes com `skillPath` em agents.json, consulte o Skill correspondente
|
|
@@ -12,12 +12,10 @@ framework/hooks/
|
|
|
12
12
|
│ ├── user-prompt/
|
|
13
13
|
│ │ └── enrich-prompt.js # Context-aware prompt enrichment
|
|
14
14
|
│ ├── pre-tool-use/
|
|
15
|
-
│ │ ├── protect-readonly-files.js # Block edits to state.json & framework/
|
|
16
15
|
│ │ ├── protect-spec-files.js # Block edits to approved spec artifacts
|
|
17
16
|
│ │ └── enforce-phase-writes.js # Enforce writes to correct phase dir
|
|
18
17
|
│ ├── post-tool-use/
|
|
19
|
-
│ │
|
|
20
|
-
│ │ └── dispatch.js # Dispatch on CLI commands
|
|
18
|
+
│ │ └── dispatch.js # Dispatch on CLI commands (auto-checkpoint)
|
|
21
19
|
│ ├── stop/
|
|
22
20
|
│ │ └── validate-completion.js # Advisory: warn about incomplete work
|
|
23
21
|
│ ├── pre-compact/
|
|
@@ -85,7 +83,6 @@ The installer writes to `.claude/settings.local.json`:
|
|
|
85
83
|
{ "matcher": "Bash", "hooks": [...] }
|
|
86
84
|
],
|
|
87
85
|
"PostToolUse": [
|
|
88
|
-
{ "matcher": "Write", "hooks": [...] },
|
|
89
86
|
{ "matcher": "Bash", "hooks": [...] }
|
|
90
87
|
],
|
|
91
88
|
"Stop": [{ "hooks": [...] }],
|
|
@@ -202,4 +199,4 @@ morph-spec doctor --reset
|
|
|
202
199
|
|
|
203
200
|
---
|
|
204
201
|
|
|
205
|
-
*MORPH-SPEC
|
|
202
|
+
*MORPH-SPEC by Polymorphism Tech — Hooks Architecture v2.5*
|
|
@@ -1,58 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Blocks direct edits to:
|
|
9
|
-
* - .morph/state.json → must use CLI commands
|
|
10
|
-
* - .morph/framework/** → read-only framework files
|
|
11
|
-
*
|
|
12
|
-
* Fail-open: exits 0 on any error.
|
|
3
|
+
* DEPRECATED — This hook has been replaced by native permissions.deny in settings.local.json.
|
|
4
|
+
* The file is kept as an empty stub. It is NOT registered in hooks-installer.js.
|
|
5
|
+
* Safe to delete.
|
|
13
6
|
*/
|
|
14
|
-
|
|
15
|
-
import { readStdin } from '../../shared/stdin-reader.js';
|
|
16
|
-
import { stateExists } from '../../shared/state-reader.js';
|
|
17
|
-
import { isStatePath, isFrameworkPath } from '../../shared/phase-utils.js';
|
|
18
|
-
import { block, pass } from '../../shared/hook-response.js';
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
// Skip if not a morph-spec project
|
|
22
|
-
if (!stateExists()) {
|
|
23
|
-
pass();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const payload = await readStdin();
|
|
27
|
-
if (!payload) pass();
|
|
28
|
-
|
|
29
|
-
const filePath = payload?.tool_input?.file_path || payload?.tool_input?.path || '';
|
|
30
|
-
if (!filePath) pass();
|
|
31
|
-
|
|
32
|
-
// Block edits to state.json
|
|
33
|
-
if (isStatePath(filePath)) {
|
|
34
|
-
block(
|
|
35
|
-
'MORPH-SPEC: Direct edits to .morph/state.json are blocked.\n' +
|
|
36
|
-
'Use CLI commands instead:\n' +
|
|
37
|
-
' morph-spec state set <feature> <key> <value>\n' +
|
|
38
|
-
' morph-spec phase advance <feature>\n' +
|
|
39
|
-
' morph-spec task done <feature> <taskId>\n' +
|
|
40
|
-
' morph-spec approve <feature> <gate>'
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Block edits to framework files
|
|
45
|
-
if (isFrameworkPath(filePath)) {
|
|
46
|
-
block(
|
|
47
|
-
'MORPH-SPEC: Files in .morph/framework/ are read-only.\n' +
|
|
48
|
-
'These files are managed by the framework and overwritten on update.\n' +
|
|
49
|
-
'To customize, create project-specific overrides in .morph/context/ or .morph/config/.'
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// All other files are allowed
|
|
54
|
-
pass();
|
|
55
|
-
} catch {
|
|
56
|
-
// Fail-open
|
|
57
|
-
process.exit(0);
|
|
58
|
-
}
|
|
7
|
+
process.exit(0);
|
|
@@ -11,13 +11,26 @@
|
|
|
11
11
|
* Fail-open: exits 0 on any error.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { loadState, getActiveFeature, getPendingGates, getMissingOutputs } from '../../shared/state-reader.js';
|
|
14
|
+
import { loadState, getActiveFeature, getPendingGates, getMissingOutputs, derivePhaseForFeature } from '../../shared/state-reader.js';
|
|
15
15
|
import { stateExists } from '../../shared/state-reader.js';
|
|
16
16
|
import { injectContext, pass } from '../../shared/hook-response.js';
|
|
17
17
|
import { readFileSync, existsSync } from 'fs';
|
|
18
18
|
import { join } from 'path';
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const DEFAULT_SPEC_MAX_CHARS = 3000;
|
|
21
|
+
|
|
22
|
+
function getSpecMaxChars() {
|
|
23
|
+
try {
|
|
24
|
+
const configPath = join(process.cwd(), '.morph/config/config.json');
|
|
25
|
+
if (!existsSync(configPath)) return DEFAULT_SPEC_MAX_CHARS;
|
|
26
|
+
const cfg = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
27
|
+
return cfg?.hooks?.specInjectionLimit ?? DEFAULT_SPEC_MAX_CHARS;
|
|
28
|
+
} catch {
|
|
29
|
+
return DEFAULT_SPEC_MAX_CHARS;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const SPEC_MAX_CHARS = getSpecMaxChars();
|
|
21
34
|
|
|
22
35
|
try {
|
|
23
36
|
if (!stateExists()) pass();
|
|
@@ -30,7 +43,8 @@ try {
|
|
|
30
43
|
|
|
31
44
|
if (active) {
|
|
32
45
|
const { name, feature } = active;
|
|
33
|
-
|
|
46
|
+
const phase = derivePhaseForFeature(name);
|
|
47
|
+
lines.push(`- Active feature: ${name} (phase: ${phase}, workflow: ${feature.workflow || 'auto'})`);
|
|
34
48
|
lines.push(`- Status: ${feature.status}`);
|
|
35
49
|
|
|
36
50
|
// Task progress
|
|
@@ -78,8 +92,9 @@ try {
|
|
|
78
92
|
const featureNames = Object.keys(state.features);
|
|
79
93
|
lines.push(`- Features: ${featureNames.length} (${featureNames.join(', ')})`);
|
|
80
94
|
|
|
81
|
-
for (const [
|
|
82
|
-
|
|
95
|
+
for (const [fname, feat] of Object.entries(state.features)) {
|
|
96
|
+
const fPhase = derivePhaseForFeature(fname);
|
|
97
|
+
lines.push(` - ${fname}: phase=${fPhase}, status=${feat.status}`);
|
|
83
98
|
}
|
|
84
99
|
}
|
|
85
100
|
|
|
@@ -347,7 +347,12 @@ def get_session_name(entries):
|
|
|
347
347
|
def get_block_start(transcript_path, entries):
|
|
348
348
|
"""Find start of current 5-hour billing block. Cached per transcript."""
|
|
349
349
|
h = hashlib.sha256(transcript_path.encode()).hexdigest()[:16]
|
|
350
|
-
|
|
350
|
+
# Use platform-appropriate cache directory
|
|
351
|
+
if os.name == 'nt':
|
|
352
|
+
base = Path(os.environ.get('LOCALAPPDATA', str(Path.home() / 'AppData' / 'Local')))
|
|
353
|
+
cache_dir = base / 'morph-spec' / 'cache'
|
|
354
|
+
else:
|
|
355
|
+
cache_dir = Path.home() / '.cache' / 'morph-spec'
|
|
351
356
|
cache_file = cache_dir / f'block-{h}.json'
|
|
352
357
|
now = time.time()
|
|
353
358
|
block_s = 5 * 3600
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Dev Stop Hook: Sync Health Check (Advisory)
|
|
5
|
+
*
|
|
6
|
+
* Event: Stop
|
|
7
|
+
* Scope: Framework codebase only (dev hook)
|
|
8
|
+
*
|
|
9
|
+
* When Claude stops, checks for out-of-sync conditions:
|
|
10
|
+
* 1. Templates not in REGISTRY.json
|
|
11
|
+
* 2. Standards not in STANDARDS.json
|
|
12
|
+
*
|
|
13
|
+
* Uses readdirSync (no git dependency, fast).
|
|
14
|
+
* Returns advisory context if out-of-sync items found.
|
|
15
|
+
*
|
|
16
|
+
* Fail-open: exits 0 on any error.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readdirSync, readFileSync, existsSync } from 'fs';
|
|
20
|
+
import { join } from 'path';
|
|
21
|
+
import { injectContext, pass } from '../shared/hook-response.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Recursively collect .md files from a directory.
|
|
25
|
+
* @param {string} dir - Directory to scan
|
|
26
|
+
* @param {string} [base] - Base path for relative paths
|
|
27
|
+
* @returns {string[]} Relative paths
|
|
28
|
+
*/
|
|
29
|
+
function collectMdFiles(dir, base) {
|
|
30
|
+
base = base || dir;
|
|
31
|
+
const results = [];
|
|
32
|
+
if (!existsSync(dir)) return results;
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
const fullPath = join(dir, entry.name);
|
|
38
|
+
if (entry.isDirectory()) {
|
|
39
|
+
if (entry.name === 'node_modules') continue;
|
|
40
|
+
results.push(...collectMdFiles(fullPath, base));
|
|
41
|
+
} else if (entry.name.endsWith('.md') && entry.name !== 'README.md') {
|
|
42
|
+
const rel = fullPath.replace(base + '/', '').replace(base + '\\', '').replace(/\\/g, '/');
|
|
43
|
+
results.push(rel);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
// Fail-open
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return results;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
// Prevent infinite loop
|
|
55
|
+
if (process.env.MORPH_STOP_HOOK_ACTIVE === '1') pass();
|
|
56
|
+
|
|
57
|
+
const warnings = [];
|
|
58
|
+
|
|
59
|
+
// Check templates vs REGISTRY.json
|
|
60
|
+
const registryPath = 'framework/templates/REGISTRY.json';
|
|
61
|
+
if (existsSync(registryPath)) {
|
|
62
|
+
try {
|
|
63
|
+
const registry = JSON.parse(readFileSync(registryPath, 'utf-8'));
|
|
64
|
+
const registeredPaths = new Set((registry.templates || []).map(t => t.path));
|
|
65
|
+
const templateFiles = collectMdFiles('framework/templates');
|
|
66
|
+
|
|
67
|
+
const unregistered = templateFiles.filter(f => !registeredPaths.has(f));
|
|
68
|
+
if (unregistered.length > 0) {
|
|
69
|
+
warnings.push(`Templates not in REGISTRY.json (${unregistered.length}):`);
|
|
70
|
+
for (const f of unregistered.slice(0, 5)) {
|
|
71
|
+
warnings.push(` - ${f}`);
|
|
72
|
+
}
|
|
73
|
+
if (unregistered.length > 5) {
|
|
74
|
+
warnings.push(` ... and ${unregistered.length - 5} more`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
// Skip on error
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check standards vs STANDARDS.json
|
|
83
|
+
const standardsPath = 'framework/standards/STANDARDS.json';
|
|
84
|
+
if (existsSync(standardsPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const registry = JSON.parse(readFileSync(standardsPath, 'utf-8'));
|
|
87
|
+
const registeredPaths = new Set((registry.standards || []).map(s => s.path));
|
|
88
|
+
const standardFiles = collectMdFiles('framework/standards');
|
|
89
|
+
|
|
90
|
+
const unregistered = standardFiles.filter(f => !registeredPaths.has(f));
|
|
91
|
+
if (unregistered.length > 0) {
|
|
92
|
+
warnings.push(`Standards not in STANDARDS.json (${unregistered.length}):`);
|
|
93
|
+
for (const f of unregistered.slice(0, 5)) {
|
|
94
|
+
warnings.push(` - ${f}`);
|
|
95
|
+
}
|
|
96
|
+
if (unregistered.length > 5) {
|
|
97
|
+
warnings.push(` ... and ${unregistered.length - 5} more`);
|
|
98
|
+
}
|
|
99
|
+
warnings.push(' Run: node scripts/generate-standards-registry.js');
|
|
100
|
+
}
|
|
101
|
+
} catch {
|
|
102
|
+
// Skip on error
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (warnings.length === 0) pass();
|
|
107
|
+
|
|
108
|
+
const message = [
|
|
109
|
+
'MORPH-SPEC Dev: Out-of-sync items detected:',
|
|
110
|
+
...warnings.map(w => ` ${w}`),
|
|
111
|
+
].join('\n');
|
|
112
|
+
|
|
113
|
+
injectContext(message);
|
|
114
|
+
} catch {
|
|
115
|
+
// Fail-open
|
|
116
|
+
process.exit(0);
|
|
117
|
+
}
|