@polymorphism-tech/morph-spec 4.12.0 → 4.14.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/CLAUDE.md +7 -7
- package/README.md +28 -34
- package/bin/morph-spec.js +41 -24
- package/bin/task-manager.js +962 -1341
- package/bin/validate.js +1 -1
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +14 -16
- package/docs/QUICKSTART.md +15 -15
- package/framework/CLAUDE.md +5 -2
- package/framework/agents/README.md +3 -4
- package/framework/agents/ai-agents/ai-system-architect.md +6 -10
- package/framework/agents/architecture/seo-growth-hacker.md +166 -326
- package/framework/agents/architecture/standards-architect.md +21 -31
- package/framework/agents/backend/dotnet-senior.md +160 -86
- package/framework/agents/backend/ef-modeler.md +2 -6
- package/framework/agents/backend/hangfire-orchestrator.md +8 -9
- package/framework/agents/backend/ms-agent-expert.md +1 -1
- package/framework/agents/frontend/nextjs-expert.md +198 -133
- package/framework/agents/frontend/ui-ux-designer.md +226 -267
- package/framework/agents/infrastructure/infra-architect.md +191 -27
- package/framework/agents/integrations/clerk-auth.md +19 -26
- package/framework/agents/integrations/hangfire-integration.md +1 -4
- package/framework/agents.json +1084 -2278
- package/framework/commands/morph-apply.md +4 -6
- package/framework/commands/morph-preflight.md +192 -269
- package/framework/commands/morph-proposal.md +210 -238
- package/framework/commands/morph-status.md +72 -92
- package/framework/commands/morph-troubleshoot.md +6 -13
- package/framework/hooks/README.md +1 -6
- package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +4 -6
- package/framework/hooks/claude-code/pre-compact/save-morph-context.js +12 -7
- package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +2 -2
- package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +2 -2
- package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +5 -10
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +63 -30
- package/framework/hooks/claude-code/session-start/resume-context.js +77 -0
- package/framework/hooks/claude-code/statusline.py +4 -5
- package/framework/hooks/claude-code/stop/validate-completion.js +4 -4
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +8 -8
- package/framework/hooks/shared/compact-restore.js +28 -5
- package/framework/hooks/shared/phase-utils.js +4 -8
- package/framework/hooks/shared/state-reader.js +34 -3
- package/framework/phases.json +162 -200
- package/framework/rules/ai-agents-standards.md +15 -0
- package/framework/rules/asaas-standards.md +13 -0
- package/framework/rules/clerk-standards.md +13 -0
- package/framework/rules/csharp-standards.md +8 -4
- package/framework/rules/data-standards.md +18 -0
- package/framework/rules/dotnet-templates.md +87 -0
- package/framework/rules/frontend-standards.md +13 -13
- package/framework/rules/hangfire-standards.md +13 -0
- package/framework/rules/infrastructure-standards.md +27 -16
- package/framework/rules/morph-workflow.md +73 -13
- package/framework/rules/nextjs-standards.md +1 -0
- package/framework/rules/nextjs-templates.md +40 -0
- package/framework/rules/resend-standards.md +12 -0
- package/framework/rules/supabase-standards.md +29 -0
- package/framework/skills/README.md +6 -8
- package/framework/skills/level-0-meta/mcp-registry.json +21 -99
- package/framework/{standards/ai-agents/team-orchestration.md → skills/level-0-meta/morph-agent-teams/SKILL.md} +472 -479
- package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +28 -1
- package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
- package/framework/skills/level-0-meta/morph-code-review/SKILL.md +1 -5
- package/framework/skills/level-0-meta/morph-code-review/scripts/scan-csharp.mjs +1 -1
- package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +23 -41
- package/framework/skills/level-0-meta/morph-init/SKILL.md +18 -14
- package/framework/skills/level-0-meta/morph-parallel-dispatch/SKILL.md +225 -0
- package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +20 -0
- package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +4 -8
- package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +15 -59
- package/framework/skills/level-0-meta/morph-verification-before-completion/SKILL.md +7 -19
- package/framework/skills/level-0-meta/morph-verification-before-completion/scripts/check-phase-outputs.mjs +8 -8
- package/framework/skills/level-1-workflows/README.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +49 -50
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +57 -123
- package/framework/skills/level-1-workflows/morph-phase-design/references/architecture-analysis-guide.md +5 -50
- package/framework/skills/level-1-workflows/morph-phase-design/references/spec-example.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +127 -159
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +4 -3
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +2 -2
- package/framework/skills/level-1-workflows/morph-phase-implement/references/recap-example.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +17 -13
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +22 -40
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -172
- package/framework/skills/level-1-workflows/morph-phase-tasks/references/tasks-example.md +5 -5
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +57 -77
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/framework/squad-templates/backend-only.json +6 -6
- package/framework/squad-templates/frontend-only.json +17 -8
- package/framework/squad-templates/full-stack.json +29 -24
- package/framework/standards/STANDARDS.json +1021 -2369
- package/framework/standards/backend/dotnet/fluent-validation-vsa.md +200 -0
- package/framework/standards/backend/dotnet/result-pattern.md +213 -0
- package/framework/standards/backend/dotnet/scalar-ui.md +172 -0
- package/framework/standards/backend/dotnet/scrutor.md +158 -0
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -0
- package/framework/standards/frontend/nextjs/motion-patterns.md +1 -1
- package/framework/standards/infrastructure/supabase/mcp-setup.md +83 -193
- package/framework/standards/integration/mcp/mcp-tools.md +91 -77
- package/framework/templates/IDE-SNIPPETS.md +2 -6
- package/framework/templates/README.md +709 -814
- package/framework/templates/REGISTRY.json +223 -762
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -0
- package/framework/templates/code/dotnet/abstractions/error.cs +60 -0
- package/framework/templates/code/dotnet/abstractions/handler.cs +12 -0
- package/framework/templates/code/dotnet/abstractions/result.cs +74 -0
- package/framework/templates/code/dotnet/backend/repository.cs +148 -141
- package/framework/templates/code/dotnet/constants/api-tags.cs +6 -0
- package/framework/templates/code/dotnet/exceptions/exception-handler.cs +32 -0
- package/framework/templates/code/dotnet/extensions/database-extensions.cs +20 -0
- package/framework/templates/code/dotnet/extensions/handler-registration.cs +38 -0
- package/framework/templates/code/dotnet/extensions/health-checks.cs +24 -0
- package/framework/templates/code/dotnet/extensions/map-endpoints.cs +35 -0
- package/framework/templates/code/dotnet/extensions/result-extensions.cs +29 -0
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -0
- package/framework/templates/code/dotnet/feature/entity.cs.hbs +8 -0
- package/framework/templates/code/dotnet/feature/errors.cs.hbs +8 -0
- package/framework/templates/code/dotnet/feature/handler.cs.hbs +24 -0
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -0
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -0
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -0
- package/framework/templates/code/dotnet/jobs/job.cs +21 -17
- package/framework/templates/code/dotnet/pipelines/logging-decorator.cs +31 -0
- package/framework/templates/code/dotnet/pipelines/validation-decorator.cs +97 -0
- package/framework/templates/code/dotnet/test.cs +192 -106
- package/framework/templates/context/ARCHITECTURE.md +89 -0
- package/framework/templates/context/CONTEXT-FEATURE.md +2 -2
- package/framework/templates/context/CONTEXT.md +180 -181
- package/framework/templates/context/design-system.md +1 -5
- package/framework/templates/docs/onboarding.md +2 -3
- package/framework/templates/docs/proposal.md +171 -182
- package/framework/templates/docs/spec.md +1 -3
- package/framework/templates/docs/ui-components.md +0 -72
- package/framework/templates/examples/design-system-examples.md +4 -4
- package/framework/templates/feature/decisions.md +0 -66
- package/framework/templates/feature/recap.md +1 -2
- package/framework/templates/infrastructure/github/README.md +56 -593
- package/framework/templates/integrations/clerk-config.cs +0 -41
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +2 -2
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -2
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +83 -126
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +2 -2
- package/framework/templates/project/validate.js +2 -4
- package/framework/templates/ui/design-system.css +1 -1
- package/framework/workflows/README.md +8 -8
- package/framework/workflows/configs/fast-track.json +51 -0
- package/framework/workflows/configs/full.json +68 -0
- package/framework/workflows/configs/standard.json +7 -3
- package/framework/workflows/docs/STORY-DRIVEN-DEVELOPMENT.md +1 -1
- package/framework/workflows/docs/enforcement-pipeline.md +18 -19
- package/framework/workflows/docs/full-morph.md +69 -76
- package/framework/workflows/docs/standard.md +49 -44
- package/framework/workflows/docs/ui-refresh.md +1 -1
- package/package.json +3 -3
- package/src/commands/agents/dispatch-agents.js +55 -116
- package/src/commands/context/context-refresh.js +79 -0
- package/src/commands/phase/phase-reset.js +1 -1
- package/src/commands/project/doctor.js +10 -32
- package/src/commands/project/init.js +12 -0
- package/src/commands/project/status.js +6 -12
- package/src/commands/scaffold/scaffold.js +131 -0
- package/src/commands/scope/escalate.js +1 -1
- package/src/commands/state/advance-phase.js +15 -29
- package/src/commands/state/state.js +20 -5
- package/src/commands/tasks/task.js +0 -30
- package/src/commands/validation/validate-feature.js +3 -10
- package/src/core/paths/output-schema.js +12 -13
- package/src/core/state/phase-state-machine.js +211 -217
- package/src/core/state/state-manager.js +9 -9
- package/src/lib/agents/agents-manager.js +2 -2
- package/src/lib/agents/output-collector.js +1 -2
- package/src/lib/detectors/design-system-detector.js +4 -4
- package/src/lib/detectors/index.js +1 -11
- package/src/lib/generators/architecture-scanner.js +640 -0
- package/src/lib/generators/context-generator.js +3 -3
- package/src/lib/generators/design-system-generator.js +508 -587
- package/src/lib/generators/index.js +12 -10
- package/src/lib/generators/metadata-extractor.js +386 -387
- package/src/lib/generators/recap-generator.js +4 -4
- package/src/lib/generators/scaffold-generator.js +317 -0
- package/src/lib/generators/settings-generator.js +0 -1
- package/src/lib/phase-chain/phase-validator.js +64 -42
- package/src/lib/stack/stack-profile.js +2 -2
- package/src/lib/standards/digest-builder.js +72 -285
- package/src/lib/tasks/task-parser.js +11 -5
- package/src/lib/validators/architecture/architecture-validator.js +259 -387
- package/src/lib/validators/content/content-validator.js +287 -287
- package/src/lib/validators/css/css-validator.js +340 -352
- package/src/lib/validators/packages/package-validator.js +347 -360
- package/src/lib/validators/shared/issue-counter.js +14 -18
- package/src/lib/validators/validation-runner.js +3 -19
- package/src/scripts/setup-infra.js +1 -1
- package/src/utils/agents-installer.js +61 -10
- package/src/utils/file-copier.js +1 -0
- package/src/utils/hooks-installer.js +11 -19
- package/src/utils/skills-installer.js +178 -178
- package/framework/agents/architecture/prompt-engineer.md +0 -195
- package/framework/agents/backend/api-designer.md +0 -106
- package/framework/agents/frontend/blazor-builder.md +0 -229
- package/framework/agents/frontend/nextjs-ui-specialist.md +0 -218
- package/framework/agents/infrastructure/azure-architect.md +0 -150
- package/framework/agents/infrastructure/azure-deploy-specialist.md +0 -707
- package/framework/agents/infrastructure/bicep-architect.md +0 -132
- package/framework/agents/infrastructure/container-specialist.md +0 -137
- package/framework/agents/infrastructure/devops-engineer.md +0 -126
- package/framework/agents/integrations/azure-identity.md +0 -148
- package/framework/agents/quality/code-analyzer.md +0 -239
- package/framework/agents/quality/testing-specialist.md +0 -130
- package/framework/hooks/claude-code/notification/approval-reminder.js +0 -57
- package/framework/hooks/claude-code/post-tool-use/context-refresh.js +0 -109
- package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +0 -78
- package/framework/index/troubleshooting-index.json +0 -184
- package/framework/rules/testing-standards.md +0 -14
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +0 -230
- package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +0 -70
- package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +0 -256
- package/framework/skills/level-1-workflows/morph-phase-clarify/references/clarifications-example.md +0 -117
- package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +0 -269
- package/framework/standards/ai-agents/blazor-ui.md +0 -364
- package/framework/standards/architecture/ddd/aggregates.md +0 -120
- package/framework/standards/architecture/ddd/bounded-contexts.md +0 -105
- package/framework/standards/architecture/ddd/complexity-levels.md +0 -108
- package/framework/standards/architecture/ddd/entities.md +0 -99
- package/framework/standards/architecture/ddd/ubiquitous-language.md +0 -58
- package/framework/standards/architecture/ddd/value-objects.md +0 -124
- package/framework/standards/backend/api/minimal-api.md +0 -494
- package/framework/standards/backend/api/rest.md +0 -492
- package/framework/standards/backend/authentication/passkeys.md +0 -428
- package/framework/standards/backend/database/ef-core.md +0 -199
- package/framework/standards/backend/database/migrations.md +0 -393
- package/framework/standards/backend/database/repository-patterns.md +0 -528
- package/framework/standards/backend/dotnet/async.md +0 -366
- package/framework/standards/backend/dotnet/core.md +0 -117
- package/framework/standards/backend/dotnet/di.md +0 -439
- package/framework/standards/backend/dotnet/program-cs-checklist.md +0 -92
- package/framework/standards/context/analytics.md +0 -96
- package/framework/standards/context/bundles.md +0 -110
- package/framework/standards/context/priming.md +0 -78
- package/framework/standards/core/architecture.md +0 -185
- package/framework/standards/core/coding.md +0 -214
- package/framework/standards/core/git-branching-strategy.md +0 -403
- package/framework/standards/core/git.md +0 -185
- package/framework/standards/core/testing.md +0 -295
- package/framework/standards/data/nosql/blob-storage.md +0 -102
- package/framework/standards/data/vector-search/azure-ai-search.md +0 -121
- package/framework/standards/frontend/blazor/design-checklist.md +0 -222
- package/framework/standards/frontend/blazor/fluent-ui-setup.md +0 -595
- package/framework/standards/frontend/blazor/fluent-ui.md +0 -137
- package/framework/standards/frontend/blazor/html-conversion.md +0 -184
- package/framework/standards/frontend/blazor/lifecycle.md +0 -195
- package/framework/standards/frontend/blazor/pitfalls.md +0 -198
- package/framework/standards/frontend/blazor/state.md +0 -191
- package/framework/standards/frontend/design-system/aesthetic-direction.md +0 -266
- package/framework/standards/frontend/design-system/design-trends.md +0 -171
- package/framework/standards/infrastructure/azure/azure.md +0 -624
- package/framework/standards/infrastructure/azure/bicep/bicep-patterns.md +0 -422
- package/framework/standards/infrastructure/azure/devops/azure-devops-setup.md +0 -516
- package/framework/standards/infrastructure/azure/devops/local-development.md +0 -520
- package/framework/standards/infrastructure/azure/services/functions.md +0 -486
- package/framework/standards/infrastructure/azure/services/service-bus.md +0 -459
- package/framework/standards/infrastructure/azure/services/storage.md +0 -407
- package/framework/standards/infrastructure/vercel/vercel-database.md +0 -106
- package/framework/standards/integration/api/graphql.md +0 -91
- package/framework/standards/integration/api/grpc.md +0 -114
- package/framework/standards/integration/api/rest-design.md +0 -95
- package/framework/standards/integration/event-driven/cqrs.md +0 -101
- package/framework/standards/integration/event-driven/event-sourcing.md +0 -124
- package/framework/standards/integration/event-driven/service-bus.md +0 -95
- package/framework/standards/observability/logging.md +0 -131
- package/framework/standards/observability/metrics.md +0 -121
- package/framework/standards/observability/monitoring.md +0 -114
- package/framework/standards/observability/tracing.md +0 -132
- package/framework/standards/workflows/parallel-execution.md +0 -112
- package/framework/standards/workflows/thread-management.md +0 -113
- package/framework/templates/code/dotnet/backend/service.cs +0 -139
- package/framework/templates/code/dotnet/contracts/Commands.cs +0 -74
- package/framework/templates/code/dotnet/contracts/Entities.cs +0 -25
- package/framework/templates/code/dotnet/contracts/Queries.cs +0 -74
- package/framework/templates/code/dotnet/contracts/api-contracts.cs +0 -173
- package/framework/templates/code/dotnet/contracts/contracts-level1.cs +0 -69
- package/framework/templates/code/dotnet/contracts/contracts-level2.cs +0 -86
- package/framework/templates/code/dotnet/contracts/contracts-level3.cs +0 -41
- package/framework/templates/code/dotnet/frontend/component.razor +0 -239
- package/framework/templates/infrastructure/azure/Dockerfile.example +0 -82
- package/framework/templates/infrastructure/azure/README.md +0 -286
- package/framework/templates/infrastructure/azure/app-insights.bicep +0 -63
- package/framework/templates/infrastructure/azure/app-service.bicep +0 -164
- package/framework/templates/infrastructure/azure/container-app-env.bicep +0 -49
- package/framework/templates/infrastructure/azure/container-app.bicep +0 -156
- package/framework/templates/infrastructure/azure/deploy-checklist.md +0 -426
- package/framework/templates/infrastructure/azure/deploy.ps1 +0 -229
- package/framework/templates/infrastructure/azure/deploy.sh +0 -208
- package/framework/templates/infrastructure/azure/key-vault.bicep +0 -91
- package/framework/templates/infrastructure/azure/main.bicep +0 -189
- package/framework/templates/infrastructure/azure/parameters.dev.json +0 -29
- package/framework/templates/infrastructure/azure/parameters.prod.json +0 -29
- package/framework/templates/infrastructure/azure/parameters.staging.json +0 -29
- package/framework/templates/infrastructure/azure/sql-database.bicep +0 -103
- package/framework/templates/infrastructure/azure/storage.bicep +0 -106
- package/framework/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +0 -22
- package/framework/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +0 -61
- package/framework/templates/integrations/azure-identity-config.cs +0 -288
- package/framework/templates/project-structure/dotnet-ddd.md +0 -70
- package/framework/templates/saas/subscription.cs +0 -347
- package/framework/templates/saas/tenant.cs +0 -338
- package/framework/templates/ui/FluentDesignTheme.cs +0 -149
- package/framework/templates/ui/MudTheme.cs +0 -281
- package/framework/workflows/configs/nodejs-cli.json +0 -40
- package/src/commands/standards/context-budget.js +0 -89
- package/src/lib/standards/index.js +0 -7
- package/src/lib/standards/standards-context-injector.js +0 -302
- package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +0 -316
- package/src/lib/validators/blazor/blazor-state-validator.js +0 -279
- package/src/lib/validators/blazor/blazor-validator.js +0 -369
- package/src/lib/validators/blazor/index.js +0 -9
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Find solutions for common .NET/
|
|
2
|
+
description: Find solutions for common .NET/Next.js development errors with root-cause analysis
|
|
3
3
|
argument-hint: "[error-message]"
|
|
4
4
|
allowed-tools: Read, Bash, Glob, Grep
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Troubleshoot - Find Solutions for Errors
|
|
8
8
|
|
|
9
|
-
Find solutions for common .NET/
|
|
9
|
+
Find solutions for common .NET/Next.js development errors and problems.
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
@@ -17,11 +17,10 @@ Find solutions for common .NET/Blazor/Azure development errors and problems.
|
|
|
17
17
|
## Examples
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
/morph-troubleshoot blazor.web.js 404
|
|
21
20
|
/morph-troubleshoot DbContext second operation
|
|
22
|
-
/morph-troubleshoot Azure.Identity NU1605
|
|
23
21
|
/morph-troubleshoot Include returns empty
|
|
24
22
|
/morph-troubleshoot PendingModelChanges
|
|
23
|
+
/morph-troubleshoot next/navigation error
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
## 3-Level Workflow
|
|
@@ -60,13 +59,11 @@ site:github.com/dotnet/aspnetcore {error}
|
|
|
60
59
|
site:github.com/dotnet/efcore {error}
|
|
61
60
|
|
|
62
61
|
# Stack Overflow
|
|
63
|
-
site:stackoverflow.com [blazor] {error}
|
|
64
62
|
site:stackoverflow.com [entity-framework-core] {error}
|
|
65
|
-
site:stackoverflow.com [
|
|
63
|
+
site:stackoverflow.com [next.js] {error}
|
|
66
64
|
|
|
67
65
|
# Microsoft Documentation
|
|
68
66
|
site:learn.microsoft.com {error}
|
|
69
|
-
site:learn.microsoft.com/azure {error}
|
|
70
67
|
```
|
|
71
68
|
|
|
72
69
|
**WebSearch usage example:**
|
|
@@ -80,9 +77,8 @@ If the user asks about a SignalR error:
|
|
|
80
77
|
|
|
81
78
|
| Category | Description |
|
|
82
79
|
|-----------|-----------|
|
|
83
|
-
| `blazor` | Blazor Server/WASM, components, lifecycle, rendering |
|
|
84
80
|
| `efcore` | Entity Framework Core, DbContext, migrations, queries |
|
|
85
|
-
| `
|
|
81
|
+
| `nextjs` | Next.js App Router, pages, components, routing |
|
|
86
82
|
| `auth` | Authentication, authorization, tokens, claims |
|
|
87
83
|
| `deploy` | Deployment, CI/CD, pipelines, containers |
|
|
88
84
|
|
|
@@ -118,13 +114,10 @@ When finding a solution, present in the following format:
|
|
|
118
114
|
|
|
119
115
|
| Error | Quick Fix |
|
|
120
116
|
|------|----------------|
|
|
121
|
-
| `blazor.web.js 404` | `<RequiresAspNetWebAssets>true</RequiresAspNetWebAssets>` |
|
|
122
117
|
| `PendingModelChangesWarning` | `dotnet ef migrations add <Name>` before update |
|
|
123
118
|
| `DbContext second operation` | Use `IDbContextFactory` for background tasks |
|
|
124
119
|
| `Include()` empty | Use `HasMany(x => x.Nav)` instead of `HasMany<T>()` |
|
|
125
|
-
| `
|
|
126
|
-
| `Key Vault won't load` | Don't condition on environment (IsDevelopment) |
|
|
127
|
-
| `DefaultAzureCredential slow` | Disable unused credentials |
|
|
120
|
+
| `next/navigation error` | Check App Router vs Pages Router usage |
|
|
128
121
|
|
|
129
122
|
---
|
|
130
123
|
|
|
@@ -15,14 +15,11 @@ framework/hooks/
|
|
|
15
15
|
│ │ ├── protect-spec-files.js # Block edits to approved spec artifacts
|
|
16
16
|
│ │ └── enforce-phase-writes.js # Enforce writes to correct phase dir
|
|
17
17
|
│ ├── post-tool-use/
|
|
18
|
-
│ │
|
|
19
|
-
│ │ └── context-refresh.js # Auto-refresh context on structural git commits
|
|
18
|
+
│ │ └── dispatch.js # Dispatch on CLI commands (auto-checkpoint)
|
|
20
19
|
│ ├── stop/
|
|
21
20
|
│ │ └── validate-completion.js # Advisory: warn about incomplete work
|
|
22
21
|
│ ├── pre-compact/
|
|
23
22
|
│ │ └── save-morph-context.js # Snapshot state before compaction
|
|
24
|
-
│ └── notification/
|
|
25
|
-
│ └── approval-reminder.js # Remind about pending approvals
|
|
26
23
|
├── shared/ # Reusable utilities for all hooks
|
|
27
24
|
│ ├── state-reader.js # Read-only state.json accessor
|
|
28
25
|
│ ├── phase-utils.js # Phase constants and path utilities
|
|
@@ -51,11 +48,9 @@ framework/hooks/
|
|
|
51
48
|
| **PreToolUse** (Write\|Edit) | enforce-phase-writes.js | Block | Ensures writes go to current phase directory |
|
|
52
49
|
| **PreToolUse** (Bash) | _(prompt-type inline guard)_ | Block | Blocks `rm -rf .morph/` and direct state edits via Claude's reasoning |
|
|
53
50
|
| **PostToolUse** (Bash) | dispatch.js | Dispatch | Triggers checkpoints on task completion |
|
|
54
|
-
| **PostToolUse** (Bash) | context-refresh.js | Inject context | Detects `git commit` with structural changes → instructs Claude to update `.morph/context/README.md` and `.morph/config/config.json` |
|
|
55
51
|
| **PostToolUseFailure** | handle-tool-failure.js | Logging | Appends structured JSON to .morph/logs/tool-failures.log |
|
|
56
52
|
| **Stop** | validate-completion.js | Advisory | Warns about incomplete tasks/missing outputs/pending gates |
|
|
57
53
|
| **PreCompact** | save-morph-context.js | Snapshot | Saves state to .morph/memory/ before compaction |
|
|
58
|
-
| **Notification** | approval-reminder.js | Advisory | Reminds about pending approval gates |
|
|
59
54
|
|
|
60
55
|
## Design Principles
|
|
61
56
|
|
|
@@ -24,12 +24,11 @@ import { parseTaskDoneCommand } from '../../shared/dispatch-helpers.js';
|
|
|
24
24
|
|
|
25
25
|
// Standard IDs referenced in remediation messages
|
|
26
26
|
const STANDARD_REFS = {
|
|
27
|
-
'di': '
|
|
28
|
-
'async': '
|
|
29
|
-
'security': '
|
|
30
|
-
'packages': '
|
|
27
|
+
'di': 'dependency injection best practices',
|
|
28
|
+
'async': 'async/await and CancellationToken patterns',
|
|
29
|
+
'security': 'security best practices',
|
|
30
|
+
'packages': 'NuGet package compatibility',
|
|
31
31
|
'design-system': 'frontend/design-system/naming.md#css-class-conventions',
|
|
32
|
-
'blazor': 'frontend/blazor/pitfalls.md#dbcontext-in-blazor',
|
|
33
32
|
};
|
|
34
33
|
|
|
35
34
|
try {
|
|
@@ -142,6 +141,5 @@ function getRefKey(ruleOrValidator) {
|
|
|
142
141
|
if (lower.includes('security') || lower.includes('sql') || lower.includes('xss')) return 'security';
|
|
143
142
|
if (lower.includes('package') || lower.includes('nuget')) return 'packages';
|
|
144
143
|
if (lower.includes('design') || lower.includes('css') || lower.includes('naming')) return 'design-system';
|
|
145
|
-
if (lower.includes('blazor') || lower.includes('dbcontext')) return 'blazor';
|
|
146
144
|
return null;
|
|
147
145
|
}
|
|
@@ -26,9 +26,9 @@ import { logHookActivity } from '../../shared/activity-logger.js';
|
|
|
26
26
|
import { buildRichContext, DECISIONS_MAX_CHARS, MAX_PENDING_TASKS } from '../../shared/compact-restore.js';
|
|
27
27
|
|
|
28
28
|
const PHASE_POSITIONS = {
|
|
29
|
-
proposal: 1,
|
|
29
|
+
proposal: 1,
|
|
30
30
|
uiux: 2, design: 2,
|
|
31
|
-
|
|
31
|
+
plan: 3,
|
|
32
32
|
tasks: 4,
|
|
33
33
|
implement: 5, sync: 5,
|
|
34
34
|
};
|
|
@@ -39,7 +39,7 @@ const NEXT_STEP_HINT = {
|
|
|
39
39
|
design: (n) => `Approve design gate: morph-spec approve ${n} design`,
|
|
40
40
|
uiux: (n) => `Approve UI gate: morph-spec approve ${n} uiux`,
|
|
41
41
|
tasks: (n) => `Approve tasks gate: morph-spec approve ${n} tasks`,
|
|
42
|
-
implement: (n) => `Continue implementation: morph-spec task
|
|
42
|
+
implement: (n) => `Continue implementation: morph-spec task start ${n} <next-task-id>`,
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
try {
|
|
@@ -77,11 +77,16 @@ try {
|
|
|
77
77
|
const { name: activeName, feature: activeFeature } = active;
|
|
78
78
|
const activePhase = derivePhaseForFeature(activeName);
|
|
79
79
|
let decisionsContent = '';
|
|
80
|
-
const decisionsPath = join(cwd, `.morph/features/${activeName}/
|
|
80
|
+
const decisionsPath = join(cwd, `.morph/features/${activeName}/2-design/decisions.md`);
|
|
81
81
|
if (existsSync(decisionsPath)) {
|
|
82
82
|
try { decisionsContent = readFileSync(decisionsPath, 'utf-8'); } catch { /* ignore */ }
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
let specContent = '';
|
|
85
|
+
const specPath2 = join(cwd, `.morph/features/${activeName}/2-design/spec.md`);
|
|
86
|
+
if (existsSync(specPath2)) {
|
|
87
|
+
try { specContent = readFileSync(specPath2, 'utf-8'); } catch { /* ignore */ }
|
|
88
|
+
}
|
|
89
|
+
snapshot.richContext = buildRichContext(activeFeature, activePhase, decisionsContent, specContent);
|
|
85
90
|
} catch { /* fail-open: richContext is optional */ }
|
|
86
91
|
}
|
|
87
92
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -132,7 +137,7 @@ try {
|
|
|
132
137
|
lines.push('Next pending tasks:');
|
|
133
138
|
for (const t of pending) lines.push(` [${t.id}] ${t.title}`);
|
|
134
139
|
if (taskList.filter(t => t.status === 'pending').length > MAX_PENDING_TASKS) {
|
|
135
|
-
lines.push(` ... (
|
|
140
|
+
lines.push(` ... (see tasks.md for full list)`);
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
|
|
@@ -164,7 +169,7 @@ try {
|
|
|
164
169
|
}
|
|
165
170
|
|
|
166
171
|
// Key decisions (truncated to stay within context budget)
|
|
167
|
-
const decisionsPath = join(cwd, `.morph/features/${name}/
|
|
172
|
+
const decisionsPath = join(cwd, `.morph/features/${name}/2-design/decisions.md`);
|
|
168
173
|
if (existsSync(decisionsPath)) {
|
|
169
174
|
try {
|
|
170
175
|
const raw = readFileSync(decisionsPath, 'utf-8');
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Ensures writes to .morph/features/{feature}/ go to the current phase's subfolder:
|
|
9
9
|
* proposal → only 0-proposal/
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* uiux → only 1-ui/
|
|
11
|
+
* design, clarify → only 2-design/
|
|
12
12
|
* tasks → only 4-tasks/
|
|
13
13
|
* implement → 5-implement/ + any source code (unrestricted)
|
|
14
14
|
*
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Event: PreToolUse | Matcher: Write|Edit
|
|
7
7
|
*
|
|
8
8
|
* Blocks Write/Edit to spec artifacts after their approval gate has passed:
|
|
9
|
-
* -
|
|
9
|
+
* - 2-design/spec.md, contracts.cs, etc. → blocked if 'design' gate approved
|
|
10
10
|
* - 4-tasks/tasks.md → blocked if 'tasks' gate approved
|
|
11
|
-
* -
|
|
11
|
+
* - 1-ui/design-system.md, etc. → blocked if 'uiux' gate approved
|
|
12
12
|
*
|
|
13
13
|
* Fail-open: exits 0 on any error.
|
|
14
14
|
*/
|
|
@@ -36,23 +36,18 @@ try {
|
|
|
36
36
|
const phase = feature.phase || derivePhaseForFeature(name);
|
|
37
37
|
if (phase !== 'implement') pass();
|
|
38
38
|
|
|
39
|
-
// Check if any task is in_progress
|
|
40
|
-
|
|
39
|
+
// Check if any task is in_progress (read directly from taskList)
|
|
40
|
+
if (feature.taskList?.some(t => t.status === 'in_progress')) pass();
|
|
41
|
+
// Fallback: legacy counter check
|
|
41
42
|
if (feature.tasks?.inProgress > 0) pass();
|
|
42
43
|
|
|
43
|
-
// Method 2: taskList array (v2 state format)
|
|
44
|
-
if (feature.taskList) {
|
|
45
|
-
const hasActive = feature.taskList.some(t => t.status === 'in_progress');
|
|
46
|
-
if (hasActive) pass();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
44
|
// No task in_progress — inject advisory warning
|
|
50
45
|
approve(
|
|
51
46
|
`[morph-spec] WARNING: No active task tracking detected during implement phase.\n` +
|
|
52
47
|
`Before writing code, start a task:\n` +
|
|
53
|
-
` morph-spec task next ${name} # see what's next\n` +
|
|
54
48
|
` morph-spec task start ${name} <id> # mark it in progress\n` +
|
|
55
|
-
`Task tracking ensures validators run, checkpoints fire, and progress is recorded
|
|
49
|
+
`Task tracking ensures validators run, checkpoints fire, and progress is recorded.\n` +
|
|
50
|
+
`If a task is more complex than expected, use: morph-spec task expand ${name} <id> --into "T00Xa: Sub" "T00Xb: Sub"`
|
|
56
51
|
);
|
|
57
52
|
} catch {
|
|
58
53
|
// Fail-open
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
* Fail-open: exits 0 on any error.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { loadState, getActiveFeature, getPendingGates, getMissingOutputs, derivePhaseForFeature } from '../../shared/state-reader.js';
|
|
14
|
+
import { loadState, getActiveFeature, getPendingGates, getMissingOutputs, derivePhaseForFeature, getTaskStats } 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 { resetActivity, logHookActivity } from '../../shared/activity-logger.js';
|
|
18
|
-
import { readFileSync, existsSync, writeFileSync, renameSync, unlinkSync } from 'fs';
|
|
18
|
+
import { readFileSync, existsSync, writeFileSync, renameSync, unlinkSync, statSync } from 'fs';
|
|
19
19
|
import { join } from 'path';
|
|
20
20
|
import { resetStaleTasks } from '../../shared/stale-task-reset.js';
|
|
21
21
|
import { execSync as _execSync } from 'child_process';
|
|
22
22
|
import { parseWorktreeResult, buildWorktreeContextLine, buildWorktreeResumeContext } from '../../shared/worktree-helpers.js';
|
|
23
23
|
|
|
24
|
-
const DEFAULT_SPEC_MAX_CHARS =
|
|
24
|
+
const DEFAULT_SPEC_MAX_CHARS = 6000;
|
|
25
25
|
|
|
26
26
|
function getSpecMaxChars() {
|
|
27
27
|
try {
|
|
@@ -90,6 +90,29 @@ try {
|
|
|
90
90
|
// ────────────────────────────────────────────────────────────────────────────
|
|
91
91
|
|
|
92
92
|
const lines = ['MORPH-SPEC Status:'];
|
|
93
|
+
|
|
94
|
+
// ── Context freshness check ─────────────────────────────────────────────
|
|
95
|
+
// If .morph/context/README.md is missing or older than 24h, suggest refresh.
|
|
96
|
+
try {
|
|
97
|
+
const contextReadmePath = join(process.cwd(), '.morph/context/README.md');
|
|
98
|
+
let contextStale = false;
|
|
99
|
+
if (!existsSync(contextReadmePath)) {
|
|
100
|
+
contextStale = true;
|
|
101
|
+
} else {
|
|
102
|
+
const stat = statSync(contextReadmePath);
|
|
103
|
+
const ageMs = Date.now() - stat.mtimeMs;
|
|
104
|
+
const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000;
|
|
105
|
+
contextStale = ageMs > TWENTY_FOUR_HOURS;
|
|
106
|
+
}
|
|
107
|
+
if (contextStale) {
|
|
108
|
+
lines.push('');
|
|
109
|
+
lines.push('⚠ Architecture context is stale or missing. Run: morph-spec context refresh');
|
|
110
|
+
}
|
|
111
|
+
} catch {
|
|
112
|
+
// Fail-open — context freshness check must never block the session
|
|
113
|
+
}
|
|
114
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
115
|
+
|
|
93
116
|
if (staleResetLog.length > 0) {
|
|
94
117
|
lines.push(`⚠️ ${staleResetLog.length} task(s) auto-reset in_progress → pending (orphaned from previous session): ${staleResetLog.join(', ')}`);
|
|
95
118
|
}
|
|
@@ -100,9 +123,10 @@ try {
|
|
|
100
123
|
lines.push(`- Active feature: ${name} (phase: ${phase}, workflow: ${feature.workflow || 'auto'})`);
|
|
101
124
|
lines.push(`- Status: ${feature.status}`);
|
|
102
125
|
|
|
103
|
-
// Task progress
|
|
104
|
-
|
|
105
|
-
|
|
126
|
+
// Task progress (read directly from taskList)
|
|
127
|
+
const stats = getTaskStats(feature);
|
|
128
|
+
if (stats.total > 0) {
|
|
129
|
+
lines.push(`- Tasks: ${stats.completed}/${stats.total} completed`);
|
|
106
130
|
}
|
|
107
131
|
|
|
108
132
|
// Pending approvals
|
|
@@ -124,16 +148,8 @@ try {
|
|
|
124
148
|
lines.push(`- Last checkpoint: #${lastCp.checkpointNum} (${lastCp.passed ? 'passed' : 'failed'})`);
|
|
125
149
|
}
|
|
126
150
|
|
|
127
|
-
// Task tracking guidance for work phases
|
|
128
|
-
if (['proposal', 'setup', 'uiux', 'design', 'clarify', 'plan', 'tasks', 'implement'].includes(phase)) {
|
|
129
|
-
lines.push('');
|
|
130
|
-
lines.push('⚠️ MANDATORY: Create session tasks (TaskCreate) BEFORE starting phase work.');
|
|
131
|
-
lines.push(' Analyze the phase workflow and create tasks reflecting your planned actions.');
|
|
132
|
-
lines.push(' Mark each in_progress → completed as you go. See phase skill for guidance.');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
151
|
// Trust level visibility — warn when low trust may block approval gates
|
|
136
|
-
const APPROVAL_GATE_PHASES = new Set(['proposal', '
|
|
152
|
+
const APPROVAL_GATE_PHASES = new Set(['proposal', 'design', 'tasks']);
|
|
137
153
|
if (APPROVAL_GATE_PHASES.has(phase)) {
|
|
138
154
|
const config = getProjectConfig();
|
|
139
155
|
const trustLevel = config?.trust?.level || config?.trustLevel || 'low';
|
|
@@ -150,15 +166,15 @@ try {
|
|
|
150
166
|
}
|
|
151
167
|
|
|
152
168
|
// Active feature spec (truncated for context budget)
|
|
153
|
-
const specPath = join(process.cwd(), `.morph/features/${name}/
|
|
169
|
+
const specPath = join(process.cwd(), `.morph/features/${name}/2-design/spec.md`);
|
|
154
170
|
if (existsSync(specPath)) {
|
|
155
171
|
try {
|
|
156
172
|
const specContent = readFileSync(specPath, 'utf-8');
|
|
157
173
|
const truncated = specContent.length > SPEC_MAX_CHARS
|
|
158
|
-
? specContent.slice(0, SPEC_MAX_CHARS) + `\n\n[... spec truncated — full file at .morph/features/${name}/
|
|
174
|
+
? specContent.slice(0, SPEC_MAX_CHARS) + `\n\n[... spec truncated — full file at .morph/features/${name}/2-design/spec.md]`
|
|
159
175
|
: specContent;
|
|
160
176
|
lines.push('');
|
|
161
|
-
lines.push(`--- Active feature spec (${name}/
|
|
177
|
+
lines.push(`--- Active feature spec (${name}/2-design/spec.md) ---`);
|
|
162
178
|
lines.push(truncated);
|
|
163
179
|
lines.push('--- End spec ---');
|
|
164
180
|
} catch {
|
|
@@ -249,20 +265,37 @@ try {
|
|
|
249
265
|
}
|
|
250
266
|
// ────────────────────────────────────────────────────────────────────────────
|
|
251
267
|
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
268
|
+
// ── CLI availability detection ─────────────────────────────────────────────
|
|
269
|
+
// Check which development CLIs are available for the current phase.
|
|
270
|
+
// Uses execSync with short timeout — fail-open on any error.
|
|
271
|
+
try {
|
|
272
|
+
const currentPhaseForCli = active ? derivePhaseForFeature(active.name) : '';
|
|
273
|
+
if (currentPhaseForCli) {
|
|
274
|
+
const cliChecks = [
|
|
275
|
+
{ name: 'docker', cmd: 'docker --version', phases: ['design', 'implement'] },
|
|
276
|
+
{ name: 'supabase', cmd: 'npx supabase --version', phases: ['design', 'implement'] },
|
|
277
|
+
{ name: 'psql', cmd: 'psql --version', phases: ['design', 'implement'] },
|
|
278
|
+
{ name: 'az', cmd: 'az version --output none', phases: ['implement'] },
|
|
279
|
+
{ name: 'gh', cmd: 'gh --version', phases: ['design', 'tasks', 'implement'] },
|
|
280
|
+
];
|
|
255
281
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
282
|
+
const relevant = cliChecks.filter(c => c.phases.includes(currentPhaseForCli));
|
|
283
|
+
if (relevant.length > 0) {
|
|
284
|
+
const cliStatus = relevant.map(c => {
|
|
285
|
+
try {
|
|
286
|
+
_execSync(c.cmd, { stdio: 'pipe', timeout: 5000 });
|
|
287
|
+
return `${c.name} ✓`;
|
|
288
|
+
} catch {
|
|
289
|
+
return `${c.name} ✗`;
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
lines.push(`CLIs: ${cliStatus.join(', ')}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
} catch {
|
|
296
|
+
// Fail-open — CLI detection must never block the session
|
|
265
297
|
}
|
|
298
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
266
299
|
|
|
267
300
|
injectContext(lines.join('\n'));
|
|
268
301
|
} catch {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SessionStart Hook: Resume Context Orientation
|
|
5
|
+
*
|
|
6
|
+
* Event: SessionStart | Matcher: resume
|
|
7
|
+
*
|
|
8
|
+
* Fires ONLY when a session resumes via /resume.
|
|
9
|
+
* Injects a brief orientation message so Claude immediately knows
|
|
10
|
+
* the active feature, phase, in-progress tasks, and last checkpoint.
|
|
11
|
+
*
|
|
12
|
+
* Fail-open: exits 0 on any error.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync, readFileSync } from 'fs';
|
|
16
|
+
import { join } from 'path';
|
|
17
|
+
import {
|
|
18
|
+
stateExists, getActiveFeature, derivePhaseForFeature,
|
|
19
|
+
} from '../../shared/state-reader.js';
|
|
20
|
+
import { injectContext, pass } from '../../shared/hook-response.js';
|
|
21
|
+
import { logHookActivity } from '../../shared/activity-logger.js';
|
|
22
|
+
import { SPEC_SUMMARY_MAX_CHARS } from '../../shared/compact-restore.js';
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
if (!stateExists()) pass();
|
|
26
|
+
|
|
27
|
+
const active = getActiveFeature();
|
|
28
|
+
if (!active) pass();
|
|
29
|
+
|
|
30
|
+
const { name, feature } = active;
|
|
31
|
+
const phase = derivePhaseForFeature(name);
|
|
32
|
+
const cwd = process.cwd();
|
|
33
|
+
|
|
34
|
+
const lines = [
|
|
35
|
+
`🔄 RESUME — Você está continuando a feature "${name}" na fase ${phase}.`,
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
// In-progress tasks
|
|
39
|
+
const taskList = Array.isArray(feature.taskList) ? feature.taskList : [];
|
|
40
|
+
const inProg = taskList.filter(t => t.status === 'in_progress');
|
|
41
|
+
if (inProg.length > 0) {
|
|
42
|
+
const ids = inProg.map(t => t.id).join(', ');
|
|
43
|
+
lines.push(`Tasks em progresso: ${ids}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Task progress summary
|
|
47
|
+
const tasks = feature.tasks || {};
|
|
48
|
+
if (tasks.total > 0) {
|
|
49
|
+
lines.push(`Progresso: ${tasks.completed || 0}/${tasks.total} tasks concluídas`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Last checkpoint
|
|
53
|
+
const checkpoints = Array.isArray(feature.checkpoints) ? feature.checkpoints : [];
|
|
54
|
+
if (checkpoints.length > 0) {
|
|
55
|
+
const last = checkpoints[checkpoints.length - 1];
|
|
56
|
+
lines.push(`Último checkpoint: #${last.checkpointNum} (${last.passed ? 'passed' : 'failed'})`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Spec summary (truncated)
|
|
60
|
+
const specPath = join(cwd, `.morph/features/${name}/2-design/spec.md`);
|
|
61
|
+
if (existsSync(specPath)) {
|
|
62
|
+
try {
|
|
63
|
+
const raw = readFileSync(specPath, 'utf-8');
|
|
64
|
+
const summary = raw.length > SPEC_SUMMARY_MAX_CHARS
|
|
65
|
+
? raw.slice(0, SPEC_SUMMARY_MAX_CHARS) + '\n[... truncated]'
|
|
66
|
+
: raw;
|
|
67
|
+
lines.push('');
|
|
68
|
+
lines.push('Spec summary:');
|
|
69
|
+
lines.push(summary);
|
|
70
|
+
} catch { /* non-blocking */ }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
logHookActivity('resume-context', 'SessionStart', 'resume_injected');
|
|
74
|
+
injectContext(lines.join('\n'));
|
|
75
|
+
} catch {
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
@@ -37,19 +37,18 @@ _CREATE_NO_WINDOW = 0x08000000 if os.name == 'nt' else 0
|
|
|
37
37
|
# ── MORPH framework constants (derived from phases.json / trust-manager.js) ──
|
|
38
38
|
|
|
39
39
|
PHASE_POSITIONS = {
|
|
40
|
-
'proposal': 1,
|
|
40
|
+
'proposal': 1,
|
|
41
41
|
'uiux': 2, 'design': 2,
|
|
42
|
-
'
|
|
42
|
+
'plan': 3,
|
|
43
43
|
'tasks': 4,
|
|
44
44
|
'implement': 5, 'sync': 5,
|
|
45
45
|
}
|
|
46
46
|
PHASE_LABELS = {
|
|
47
47
|
'proposal': 'proposal',
|
|
48
|
-
'setup': 'setup',
|
|
49
48
|
'uiux': 'UI/UX',
|
|
50
49
|
'design': 'design',
|
|
51
|
-
'
|
|
52
|
-
'tasks': '
|
|
50
|
+
'plan': 'planning',
|
|
51
|
+
'tasks': 'tasks',
|
|
53
52
|
'implement': 'implement',
|
|
54
53
|
'sync': 'sync',
|
|
55
54
|
}
|
|
@@ -30,7 +30,7 @@ import { logHookActivity } from '../../shared/activity-logger.js';
|
|
|
30
30
|
const COMPACT_TRIGGER_PHASES = new Set(['implement']);
|
|
31
31
|
|
|
32
32
|
// Phases where compaction is suggested when arriving from a heavy spec phase
|
|
33
|
-
const HEAVY_SOURCE_PHASES = new Set(['tasks', 'design', '
|
|
33
|
+
const HEAVY_SOURCE_PHASES = new Set(['tasks', 'design', 'uiux']);
|
|
34
34
|
|
|
35
35
|
try {
|
|
36
36
|
// Prevent infinite loop
|
|
@@ -78,7 +78,7 @@ try {
|
|
|
78
78
|
` loaded during planning take significant space. A compact now gives`,
|
|
79
79
|
` Claude a clean slate focused on writing code.`,
|
|
80
80
|
``,
|
|
81
|
-
` After /compact, resume with: morph-spec task
|
|
81
|
+
` After /compact, resume with: morph-spec task start ${name} <next-task-id>`,
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -96,7 +96,7 @@ try {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// Missing outputs in spec phases
|
|
99
|
-
if (['proposal', 'design', '
|
|
99
|
+
if (['proposal', 'design', 'tasks', 'uiux'].includes(currentPhase)) {
|
|
100
100
|
const missing = getMissingOutputs(name);
|
|
101
101
|
if (missing.length > 0) {
|
|
102
102
|
warnings.push(`Missing outputs for '${name}' (${currentPhase} phase):`);
|
|
@@ -124,7 +124,7 @@ try {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// ── MEMORY.md reminder ────────────────────────────────────────────────────
|
|
127
|
-
const WORK_PHASES = new Set(['design', '
|
|
127
|
+
const WORK_PHASES = new Set(['design', 'tasks', 'implement']);
|
|
128
128
|
const memoryLines = [];
|
|
129
129
|
if (WORK_PHASES.has(currentPhase)) {
|
|
130
130
|
memoryLines.push('📝 Sessão encerrando. Considere salvar no MEMORY.md:');
|
|
@@ -39,8 +39,11 @@ try {
|
|
|
39
39
|
if (promptLower.includes(featureName.toLowerCase())) {
|
|
40
40
|
const featurePhase = feature.phase || derivePhaseForFeature(featureName);
|
|
41
41
|
context.push(`[morph-spec] Feature '${featureName}': phase=${featurePhase}, status=${feature.status}`);
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
const taskList = feature.taskList || [];
|
|
43
|
+
const activeTasks = taskList.filter(t => t.status !== 'expanded');
|
|
44
|
+
if (activeTasks.length > 0) {
|
|
45
|
+
const completed = activeTasks.filter(t => t.status === 'completed').length;
|
|
46
|
+
context.push(` Tasks: ${completed}/${activeTasks.length} completed`);
|
|
44
47
|
}
|
|
45
48
|
break; // Only inject for the first matched feature
|
|
46
49
|
}
|
|
@@ -64,15 +67,12 @@ try {
|
|
|
64
67
|
|
|
65
68
|
// Coding intent during implement phase but no task in_progress
|
|
66
69
|
if (wantsToCode && activePhase === 'implement') {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
hasActiveTask = feature.taskList.some(t => t.status === 'in_progress');
|
|
70
|
-
}
|
|
70
|
+
const hasActiveTask = feature.taskList?.some(t => t.status === 'in_progress') ||
|
|
71
|
+
feature.tasks?.inProgress > 0; // fallback for legacy state
|
|
71
72
|
if (!hasActiveTask) {
|
|
72
73
|
context.push(
|
|
73
74
|
`[morph-spec] REMINDER: No task is currently in_progress for '${name}'.` +
|
|
74
75
|
` Start a task before coding:\n` +
|
|
75
|
-
` morph-spec task next ${name} # see what's next\n` +
|
|
76
76
|
` morph-spec task start ${name} <id> # mark it in progress`
|
|
77
77
|
);
|
|
78
78
|
}
|
|
@@ -95,7 +95,7 @@ try {
|
|
|
95
95
|
if (promptLower.includes('next task') || promptLower.includes('what\'s next')) {
|
|
96
96
|
if (activePhase === 'implement') {
|
|
97
97
|
context.push(
|
|
98
|
-
`[morph-spec]
|
|
98
|
+
`[morph-spec] Check tasks.md for the next task, then: morph-spec task start ${name} <id>`
|
|
99
99
|
);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -8,17 +8,19 @@
|
|
|
8
8
|
* Pure functions — no I/O.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
export const DECISIONS_MAX_CHARS
|
|
12
|
-
export const MAX_PENDING_TASKS
|
|
11
|
+
export const DECISIONS_MAX_CHARS = 3000;
|
|
12
|
+
export const MAX_PENDING_TASKS = 8;
|
|
13
|
+
export const SPEC_SUMMARY_MAX_CHARS = 3000;
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Build the richContext object to embed in pre-compact memory file.
|
|
16
|
-
* @param {Object} feature - Feature state object (tasks, taskList)
|
|
17
|
+
* @param {Object} feature - Feature state object (tasks, taskList, checkpoints)
|
|
17
18
|
* @param {string} phase - Current derived phase string
|
|
18
19
|
* @param {string} decisionsContent - Raw text of decisions.md (may be empty string)
|
|
20
|
+
* @param {string} [specContent=''] - Raw text of spec.md (may be empty string)
|
|
19
21
|
* @returns {Object} richContext
|
|
20
22
|
*/
|
|
21
|
-
export function buildRichContext(feature, phase, decisionsContent) {
|
|
23
|
+
export function buildRichContext(feature, phase, decisionsContent, specContent = '') {
|
|
22
24
|
const taskList = Array.isArray(feature.taskList) ? feature.taskList : [];
|
|
23
25
|
|
|
24
26
|
const inProgress = taskList
|
|
@@ -34,12 +36,23 @@ export function buildRichContext(feature, phase, decisionsContent) {
|
|
|
34
36
|
? decisionsContent.slice(0, DECISIONS_MAX_CHARS)
|
|
35
37
|
: decisionsContent;
|
|
36
38
|
|
|
39
|
+
const specSummary = specContent.length > SPEC_SUMMARY_MAX_CHARS
|
|
40
|
+
? specContent.slice(0, SPEC_SUMMARY_MAX_CHARS)
|
|
41
|
+
: specContent;
|
|
42
|
+
|
|
43
|
+
const checkpoints = Array.isArray(feature.checkpoints) ? feature.checkpoints : [];
|
|
44
|
+
const lastCheckpoint = checkpoints.length > 0
|
|
45
|
+
? { passed: checkpoints[checkpoints.length - 1].passed, checkpointNum: checkpoints[checkpoints.length - 1].checkpointNum }
|
|
46
|
+
: null;
|
|
47
|
+
|
|
37
48
|
return {
|
|
38
49
|
phase,
|
|
39
50
|
tasks: feature.tasks || {},
|
|
40
51
|
decisionsSnippet,
|
|
41
52
|
inProgress,
|
|
42
53
|
nextPending,
|
|
54
|
+
specSummary,
|
|
55
|
+
lastCheckpoint,
|
|
43
56
|
};
|
|
44
57
|
}
|
|
45
58
|
|
|
@@ -53,7 +66,7 @@ export function buildRestoreBlock(memorySnapshot) {
|
|
|
53
66
|
if (!rc) return null;
|
|
54
67
|
|
|
55
68
|
const { timestamp, activeFeature } = memorySnapshot;
|
|
56
|
-
const { phase, tasks, decisionsSnippet, inProgress, nextPending } = rc;
|
|
69
|
+
const { phase, tasks, decisionsSnippet, inProgress, nextPending, specSummary, lastCheckpoint } = rc;
|
|
57
70
|
|
|
58
71
|
const done = tasks?.completed ?? '?';
|
|
59
72
|
const total = tasks?.total ?? '?';
|
|
@@ -63,6 +76,16 @@ export function buildRestoreBlock(memorySnapshot) {
|
|
|
63
76
|
`Active feature: ${activeFeature} | Phase: ${phase} | Tasks: ${done}/${total}`,
|
|
64
77
|
];
|
|
65
78
|
|
|
79
|
+
if (lastCheckpoint) {
|
|
80
|
+
lines.push(`Last checkpoint: #${lastCheckpoint.checkpointNum} (${lastCheckpoint.passed ? 'passed' : 'failed'})`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (specSummary) {
|
|
84
|
+
lines.push('');
|
|
85
|
+
lines.push('Spec summary (at time of compact):');
|
|
86
|
+
lines.push(specSummary);
|
|
87
|
+
}
|
|
88
|
+
|
|
66
89
|
if (decisionsSnippet) {
|
|
67
90
|
lines.push('');
|
|
68
91
|
lines.push('Key decisions (at time of compact):');
|