@polymorphism-tech/morph-spec 8.47.0 → 9.1.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 +51 -43
- package/README.md +39 -38
- package/bin/morph-spec.js +41 -113
- package/bin/validate.js +1 -147
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +41 -101
- package/framework/MORPH.md +95 -252
- package/framework/agents.json +86 -21
- package/framework/commands/morph-apply.md +5 -28
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-hotfix.md +8 -8
- package/framework/commands/morph-infra.md +1 -1
- package/framework/commands/morph-preflight.md +2 -3
- package/framework/commands/morph-status.md +4 -4
- package/framework/docs/CLI.md +574 -286
- package/framework/evals/review-checklist.md +82 -41
- package/framework/hooks/README.md +10 -11
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +6 -49
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +2 -35
- package/framework/hooks/claude-code/core/chain.js +4 -65
- package/framework/hooks/claude-code/core/comment-guard.js +3 -17
- package/framework/hooks/claude-code/core/denylist.json +33 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +15 -63
- package/framework/hooks/claude-code/core/gate-guard.js +9 -78
- package/framework/hooks/claude-code/core/graph-refresh-kick.js +3 -24
- package/framework/hooks/claude-code/core/heavy-gate.js +3 -21
- package/framework/hooks/claude-code/core/heavy-release.js +2 -13
- package/framework/hooks/claude-code/core/loop-detect.js +2 -31
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +36 -2
- package/framework/hooks/claude-code/core/protect-spec-files.js +25 -297
- package/framework/hooks/claude-code/core/state-sync.js +15 -85
- package/framework/hooks/claude-code/core/telemetry-log.js +15 -96
- package/framework/hooks/claude-code/core/validate-completion.js +37 -147
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +23 -0
- package/framework/hooks/claude-code/core/worktree-context.js +15 -114
- package/framework/hooks/claude-code/core/worktree-create.js +6 -70
- package/framework/hooks/claude-code/core/worktree-env-inject.js +5 -56
- package/framework/hooks/claude-code/core/worktree-remove.js +5 -31
- package/framework/hooks/claude-code/statusline.py +55 -41
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/shared/activity-logger.js +9 -89
- package/framework/hooks/shared/agent-reap.js +2 -17
- package/framework/hooks/shared/build-check.js +11 -76
- package/framework/hooks/shared/claim-registry.js +9 -119
- package/framework/hooks/shared/command-tokens.js +168 -44
- package/framework/hooks/shared/comment-rules.js +5 -20
- package/framework/hooks/shared/comment-scanner.js +11 -43
- package/framework/hooks/shared/comment-stripper.js +11 -85
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/errata.js +59 -0
- package/framework/hooks/shared/feature-locator.js +11 -95
- package/framework/hooks/shared/frontend-locations.js +4 -0
- package/framework/hooks/shared/gate-question.js +12 -0
- package/framework/hooks/shared/git-exclude.js +3 -20
- package/framework/hooks/shared/git-paths.js +8 -104
- package/framework/hooks/shared/graph-freshness.js +22 -166
- package/framework/hooks/shared/graph-refresh.js +21 -149
- package/framework/hooks/shared/heavy-command.js +4 -12
- package/framework/hooks/shared/hook-response.js +8 -83
- package/framework/hooks/shared/morph-cli.js +8 -52
- package/framework/hooks/shared/payload-utils.js +10 -132
- package/framework/hooks/shared/phase-utils.js +14 -72
- package/framework/hooks/shared/redact-secrets.js +4 -15
- package/framework/hooks/shared/reparse-scan.js +6 -66
- package/framework/hooks/shared/slice-progress.js +99 -0
- package/framework/hooks/shared/source-files.js +4 -17
- package/framework/hooks/shared/spawn-command.js +23 -0
- package/framework/hooks/shared/state-reader.js +51 -247
- package/framework/hooks/shared/state-writer.js +9 -54
- package/framework/hooks/shared/stdin-reader.js +1 -11
- package/framework/hooks/shared/telemetry-logger.js +7 -67
- package/framework/hooks/shared/transcript-usage.js +7 -29
- package/framework/hooks/shared/worktree-root.js +7 -29
- package/framework/mcp/registry.json +3 -4
- package/framework/phases.json +23 -39
- package/framework/rules/csharp-standards.md +1 -1
- package/framework/rules/frontend-standards.md +1 -0
- package/framework/rules/hangfire-standards.md +1 -1
- package/framework/rules/neon-standards.md +1 -1
- package/framework/schemas/config.schema.json +14 -9
- package/framework/schemas/feature.schema.json +15 -50
- package/framework/skills/README.md +3 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +149 -222
- package/framework/skills/core/morph-hotfix/SKILL.md +33 -42
- package/framework/skills/core/morph-machine/SKILL.md +2 -2
- package/framework/skills/core/morph-media/SKILL.md +1 -1
- package/framework/skills/core/morph-plan/SKILL.md +137 -299
- package/framework/skills/core/morph-review/SKILL.md +111 -136
- package/framework/skills/core/morph-standards/SKILL.md +27 -39
- package/framework/skills/core/morph-uiux/SKILL.md +94 -152
- package/framework/standards/STANDARDS.json +109 -1219
- package/framework/standards/STANDARDS.meta.json +1319 -0
- package/framework/standards/ai-agents/agent-archetypes.md +2 -2
- package/framework/standards/ai-agents/agent-session.md +1 -1
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +4 -4
- package/framework/standards/ai-agents/durable-workflows-hitl.md +3 -3
- package/framework/standards/ai-agents/evals-with-cache.md +1 -2
- package/framework/standards/ai-agents/guardrails.md +1 -1
- package/framework/standards/ai-agents/multi-agent-patterns.md +2 -2
- package/framework/standards/ai-agents/observability-patterns.md +1 -1
- package/framework/standards/ai-agents/production.md +1 -1
- package/framework/standards/ai-agents/prompt-sources.md +2 -2
- package/framework/standards/ai-agents/providers/model-registry.md +1 -1
- package/framework/standards/ai-agents/rag-custom-pgvector.md +2 -2
- package/framework/standards/ai-agents/setup.md +3 -3
- package/framework/standards/ai-agents/sweet-spot.md +2 -2
- package/framework/standards/ai-agents/tool-adapters.md +0 -2
- package/framework/standards/ai-agents/vector-data-extensions.md +4 -4
- package/framework/standards/ai-agents/workflows.md +1 -1
- package/framework/standards/architecture/code-comments.md +7 -7
- package/framework/standards/architecture/vertical-slice/vertical-slice.md +1 -1
- package/framework/standards/backend/api/validation.md +1 -1
- package/framework/standards/backend/dotnet/vsa-handler-patterns.md +5 -5
- package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +1 -1
- package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -2
- package/framework/standards/data/nosql/cache/redis.md +1 -1
- package/framework/standards/data/nosql/cosmos-db.md +3 -3
- package/framework/standards/frontend/admin-app/forms.md +1 -1
- package/framework/standards/frontend/design-system/art-direction.md +88 -0
- package/framework/standards/frontend/design-system/premium-finish.md +77 -2
- package/framework/standards/infrastructure/neon/neon-pgvector.md +5 -5
- package/framework/standards/integration/mcp/mcp-tools.md +7 -7
- package/framework/templates/CLAUDE.md.core.template +3 -3
- package/framework/templates/README.md +2 -3
- package/framework/templates/REGISTRY.json +15 -179
- package/framework/templates/docs/plan.md +72 -0
- package/framework/templates/docs/ui-mockups.md +4 -0
- package/framework/templates/dotnet/ai-kit/README.md +1 -9
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +0 -10
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +1 -1
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +3 -4
- package/package.json +1 -1
- package/src/commands/context/context-refresh.js +0 -16
- package/src/commands/dashboard/dashboard.js +2 -8
- package/src/commands/e2e/e2e.js +18 -105
- package/src/commands/graph/affected.js +0 -14
- package/src/commands/graph/build.js +11 -50
- package/src/commands/graph/explain.js +0 -16
- package/src/commands/graph/status.js +1 -12
- package/src/commands/mcp/mcp-setup.js +4 -62
- package/src/commands/observability/cost.js +17 -111
- package/src/commands/observability/telemetry.js +1 -14
- package/src/commands/project/branch.js +4 -45
- package/src/commands/project/claim.js +4 -48
- package/src/commands/project/doctor-procs.js +1 -1
- package/src/commands/project/doctor.js +53 -307
- package/src/commands/project/env.js +1 -27
- package/src/commands/project/fleet.js +6 -35
- package/src/commands/project/heavy.js +3 -3
- package/src/commands/project/init.js +8 -68
- package/src/commands/project/install-plugin-cmd.js +0 -1
- package/src/commands/project/setup-infra-cmd.js +2 -1
- package/src/commands/project/stack-scan.js +58 -0
- package/src/commands/project/standards.js +65 -72
- package/src/commands/project/status.js +28 -121
- package/src/commands/project/update.js +31 -223
- package/src/commands/project/worktree.js +109 -883
- package/src/commands/scaffold/scaffold.js +0 -25
- package/src/commands/state/advance.js +65 -120
- package/src/commands/state/approve.js +87 -229
- package/src/commands/state/archive.js +23 -139
- package/src/commands/state/auto-approval.js +65 -0
- package/src/commands/state/create.js +49 -109
- package/src/commands/state/delete.js +11 -63
- package/src/commands/state/finish.js +105 -494
- package/src/commands/state/gate-check.js +74 -183
- package/src/commands/state/gate-decision.js +8 -42
- package/src/commands/state/handoff.js +4 -31
- package/src/commands/state/list.js +21 -91
- package/src/commands/state/report-check.js +134 -338
- package/src/commands/state/retype.js +12 -28
- package/src/commands/validation/index.js +0 -3
- package/src/commands/validation/mutate.js +79 -19
- package/src/commands/validation/plan-check.js +81 -0
- package/src/commands/validation/validate-feature.js +52 -216
- package/src/commands/validation/verify.js +45 -160
- package/src/core/paths/output-schema.js +9 -155
- package/src/core/state/feature-identity.js +1 -25
- package/src/core/state/gate-order.js +2 -30
- package/src/core/state/lifecycle-audit.js +8 -100
- package/src/core/state/state-manager.js +32 -395
- package/src/core/templates/template-registry.js +2 -97
- package/src/core/templates/template-renderer.js +13 -93
- package/src/core/templates/template-seed.js +21 -0
- package/src/core/work-types.js +10 -45
- package/src/dashboard/app/App.jsx +1 -8
- package/src/dashboard/app/components/ActivityFeed.jsx +2 -8
- package/src/dashboard/app/components/CommandPalette.jsx +4 -11
- package/src/dashboard/app/components/DetailPanel.jsx +1 -5
- package/src/dashboard/app/components/EntityLink.jsx +0 -12
- package/src/dashboard/app/components/ErrorBoundary.jsx +1 -8
- package/src/dashboard/app/components/KnowledgeMarkdown.jsx +0 -11
- package/src/dashboard/app/components/Markdown.jsx +0 -9
- package/src/dashboard/app/components/PhaseRail.jsx +0 -11
- package/src/dashboard/app/components/SearchFilter.jsx +0 -4
- package/src/dashboard/app/components/Sidebar.jsx +0 -5
- package/src/dashboard/app/hooks/useMorphQuery.js +1 -11
- package/src/dashboard/app/hooks/usePref.js +1 -5
- package/src/dashboard/app/lib/format.js +0 -2
- package/src/dashboard/app/lib/phases.js +3 -9
- package/src/dashboard/app/lib/project.js +0 -12
- package/src/dashboard/app/pages/Activity.jsx +1 -1
- package/src/dashboard/app/pages/AgentMap.jsx +1 -8
- package/src/dashboard/app/pages/FeatureDetail.jsx +139 -133
- package/src/dashboard/app/pages/Features.jsx +9 -16
- package/src/dashboard/app/pages/Guide.jsx +2 -3
- package/src/dashboard/app/pages/HookInspector.jsx +2 -23
- package/src/dashboard/app/pages/PhasePipeline.jsx +3 -7
- package/src/dashboard/app/pages/Portfolio.jsx +0 -1
- package/src/dashboard/app/pages/RulesMap.jsx +1 -16
- package/src/dashboard/app/pages/SkillsLibrary.jsx +1 -16
- package/src/dashboard/app/pages/Standards.jsx +2 -17
- package/src/dashboard/scanner/activity-scanner.js +14 -83
- package/src/dashboard/scanner/agents-scanner.js +1 -23
- package/src/dashboard/scanner/docs-scanner.js +1 -7
- package/src/dashboard/scanner/feature-status.js +2 -5
- package/src/dashboard/scanner/features-scanner.js +92 -113
- package/src/dashboard/scanner/hooks-scanner.js +5 -28
- package/src/dashboard/scanner/index.js +0 -4
- package/src/dashboard/scanner/portfolio.js +5 -29
- package/src/dashboard/scanner/project-api.js +8 -54
- package/src/dashboard/scanner/rules-scanner.js +1 -2
- package/src/dashboard/scanner/skills-scanner.js +2 -12
- package/src/dashboard/scanner/standards-scanner.js +4 -7
- package/src/dashboard/vite-plugin-morph-data.js +5 -19
- package/src/lib/ai/ai-checks.js +7 -52
- package/src/lib/ai/ai-project-scan.js +14 -108
- package/src/lib/ai/code-audit.js +7 -63
- package/src/lib/ai/pin-drift.js +8 -51
- package/src/lib/ai/registry-audit.js +11 -90
- package/src/lib/ci/ci-verify.js +14 -13
- package/src/lib/ci/github-ci.js +9 -37
- package/src/lib/ci/workflow-scaffold.js +2 -10
- package/src/lib/detectors/claude-config-detector.js +13 -74
- package/src/lib/detectors/index.js +8 -59
- package/src/lib/e2e/compose-env.js +5 -66
- package/src/lib/e2e/stack-teardown.js +6 -40
- package/src/lib/generators/architecture-scanner.js +18 -156
- package/src/lib/generators/handoff-generator.js +37 -112
- package/src/lib/generators/scaffold-generator.js +5 -101
- package/src/lib/generators/settings-generator.js +11 -122
- package/src/lib/git/branch-classifier.js +11 -84
- package/src/lib/git/default-branch.js +14 -169
- package/src/lib/git/evidence-staleness.js +2 -1
- package/src/lib/git/gh.js +2 -17
- package/src/lib/git/pending-prs.js +6 -37
- package/src/lib/git/pr-files.js +3 -28
- package/src/lib/git/pr-index.js +3 -34
- package/src/lib/git/tree-fingerprint.js +17 -17
- package/src/lib/git/tree-state.js +6 -33
- package/src/lib/graph/god-nodes.js +2 -22
- package/src/lib/graph/graph-health.js +3 -24
- package/src/lib/graph/graph-loader.js +5 -56
- package/src/lib/graph/graphify-runtime.js +7 -37
- package/src/lib/graph/graphifyignore.js +8 -74
- package/src/lib/graph/sanitize.js +16 -136
- package/src/lib/heavy/cleanup.js +2 -6
- package/src/lib/installers/effects.js +8 -93
- package/src/lib/installers/mcp-installer.js +9 -169
- package/src/lib/installers/memory-installer.js +8 -33
- package/src/lib/installers/templates-reconcile.js +5 -60
- package/src/lib/mutation/commands.js +3 -2
- package/src/lib/mutation/dotnet-introspection.js +281 -0
- package/src/lib/mutation/plan.js +14 -6
- package/src/lib/mutation/runner.js +1 -1
- package/src/lib/mutation/subset.js +47 -13
- package/src/lib/plan/artifact-vocabulary.js +40 -0
- package/src/lib/plan/checks.js +208 -0
- package/src/lib/plan/plan-parser.js +204 -0
- package/src/lib/plan/plan-template.js +18 -0
- package/src/lib/projects/registry.js +7 -44
- package/src/lib/review-reports.js +204 -0
- package/src/lib/risk-detector.js +131 -274
- package/src/lib/specs/adr-index.js +38 -85
- package/src/lib/specs/design-seed.js +18 -0
- package/src/lib/specs/frontmatter.js +31 -0
- package/src/lib/specs/gfm-table.js +11 -0
- package/src/lib/specs/revocations.js +31 -102
- package/src/lib/specs/screen-checklist.js +56 -132
- package/src/lib/stack/dotnet-build-ignores.js +43 -0
- package/src/lib/stack/stack-profile.js +1 -28
- package/src/lib/stack/stack-scan.js +260 -0
- package/src/lib/stack-filter.js +4 -27
- package/src/lib/standards/registry.js +37 -0
- package/src/lib/standards/sections.js +47 -0
- package/src/lib/standards/verified-against.js +19 -191
- package/src/lib/tasks/eval-node.js +23 -179
- package/src/lib/tasks/linux-runner.js +18 -142
- package/src/lib/tasks/test-nodes.js +43 -313
- package/src/lib/tasks/test-runner.js +107 -447
- package/src/lib/telemetry/metrics.js +13 -103
- package/src/lib/telemetry/telemetry-reader.js +13 -238
- package/src/lib/telemetry/verify-event.js +4 -34
- package/src/lib/validators/code-budget/code-budget-validator.js +4 -44
- package/src/lib/validators/code-budget/index.js +0 -7
- package/src/lib/validators/contracts/contract-compliance-validator.js +4 -26
- package/src/lib/validators/contracts/index.js +0 -6
- package/src/lib/validators/nextjs/index.js +0 -5
- package/src/lib/validators/nextjs/next-component-validator.js +4 -81
- package/src/lib/validators/packages/index.js +0 -6
- package/src/lib/validators/packages/package-validator.js +6 -56
- package/src/lib/validators/reuse/index.js +0 -8
- package/src/lib/validators/reuse/reuse-validator.js +24 -137
- package/src/lib/validators/reuse/symbol-scanner.js +6 -62
- package/src/lib/validators/traceability-check.js +54 -156
- package/src/lib/validators/validation-runner.js +20 -125
- package/src/lib/validators/verify-runner.js +152 -575
- package/src/lib/work-type-detector.js +5 -67
- package/src/lib/worktree/docker-audit.js +17 -137
- package/src/lib/worktree/env-allocator.js +10 -98
- package/src/lib/worktree/feature-truth.js +12 -115
- package/src/lib/worktree/finish-backup.js +32 -242
- package/src/lib/worktree/fleet-scanner.js +31 -126
- package/src/lib/worktree/ignored-triage.js +15 -91
- package/src/lib/worktree/vscode-settings.js +2 -3
- package/src/lib/worktree/worktree-audit.js +21 -213
- package/src/lib/worktree/worktree-include.js +3 -5
- package/src/scripts/global-install.js +3 -9
- package/src/scripts/install-plugin.js +1 -13
- package/src/scripts/setup-infra.js +17 -138
- package/src/utils/agents-installer.js +92 -272
- package/src/utils/banner.js +4 -25
- package/src/utils/claude-md-injector.js +1 -37
- package/src/utils/claude-settings-manager.js +1 -87
- package/src/utils/file-copier.js +32 -90
- package/src/utils/hooks-installer.js +26 -296
- package/src/utils/skills-installer.js +4 -102
- package/src/utils/version-checker.js +4 -83
- package/framework/commands/morph-proposal.md +0 -57
- package/framework/evals/trace-schema.md +0 -67
- package/framework/hooks/claude-code/core/tasks-json-guard.js +0 -83
- package/framework/hooks/claude-code/core/trace-autogen.js +0 -277
- package/framework/hooks/git/pre-commit/specs.sh +0 -50
- package/framework/hooks/shared/tasks-validator.js +0 -111
- package/framework/rules/morph-task-tracking.md +0 -54
- package/framework/rules/morph-workflow.md +0 -244
- package/framework/schemas/tasks.schema.json +0 -79
- package/framework/skills/core/morph-brainstorming/SKILL.md +0 -161
- package/framework/skills/core/morph-implement/SKILL.md +0 -194
- package/framework/skills/core/morph-proposal/SKILL.md +0 -152
- package/framework/skills/core/morph-stack-scan/SKILL.md +0 -145
- package/framework/templates/docs/proposal.md +0 -192
- package/framework/templates/docs/spec.md +0 -57
- package/framework/templates/docs/ui-components.md +0 -52
- package/framework/templates/docs/ui-design-system.md +0 -76
- package/framework/templates/docs/ui-flows.md +0 -167
- package/framework/templates/examples/spec-examples.md +0 -91
- package/framework/templates/feature/decisions.md +0 -124
- package/framework/templates/feature/recap.md +0 -145
- package/framework/templates/tasks.template.json +0 -17
- package/src/commands/state/usecase.js +0 -143
- package/src/commands/tasks/dag.js +0 -181
- package/src/commands/utils/index.js +0 -3
- package/src/lib/agents/output-collector.js +0 -76
- package/src/lib/detectors/design-system-detector.js +0 -188
- package/src/lib/evaluator-report.js +0 -104
- package/src/lib/generators/design-system-generator.js +0 -508
- package/src/lib/specs/acervo-format.js +0 -70
- package/src/lib/specs/acervo-lifecycle.js +0 -264
- package/src/lib/specs/done-criteria-check.js +0 -200
- package/src/lib/specs/usecase-check.js +0 -301
- package/src/lib/specs/usecase-promoter.js +0 -301
- package/src/lib/specs/usecase-registry.js +0 -237
- package/src/lib/tasks/dispatch-planner.js +0 -319
- package/src/lib/tasks/dotnet-test-introspection.js +0 -632
- package/src/lib/tasks/mermaid-renderer.js +0 -132
- package/src/lib/tasks/task-classifier.js +0 -30
- package/src/lib/tasks/task-parser.js +0 -209
- package/src/lib/tasks/tasks-json-parser.js +0 -296
- package/src/lib/tasks/test-scope.js +0 -597
- package/src/utils/agent-id-mapper.js +0 -11
|
@@ -6,33 +6,10 @@ import { isValidFeatureName, cwdIsInsideWorktree, teardownWorktree, resolvePrima
|
|
|
6
6
|
import { resolveFeatureTree } from '../../lib/worktree/feature-truth.js';
|
|
7
7
|
import { tearDownFeatureStack } from '../../lib/e2e/stack-teardown.js';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* delete = dead scaffolds and abandoned drafts you clear out.
|
|
14
|
-
*
|
|
15
|
-
* The critical guarantee — mirrored from `archive` — is that the deletion also
|
|
16
|
-
* drops the feature from the thin root index (.morph/state.json). Without that,
|
|
17
|
-
* the next `loadState` resurrects the folder from the stale index entry
|
|
18
|
-
* (turning a delete into a zombie). We edit the index directly rather than
|
|
19
|
-
* calling saveState, which would re-materialize .morph/features/{name}.
|
|
20
|
-
*
|
|
21
|
-
* Refuses when any gate is approved (real work, not a dead shell), unless
|
|
22
|
-
* `--force`.
|
|
23
|
-
*
|
|
24
|
-
* SECURITY: `featureName` is an unsanitized CLI argument that flows straight
|
|
25
|
-
* into `rmSync(..., { recursive: true })` — the same class of bug the worktree
|
|
26
|
-
* teardown guards against, but here the danger is path TRAVERSAL rather than a
|
|
27
|
-
* followed symlink. `join(cwd, '.morph', 'features', '../../.claude')`
|
|
28
|
-
* resolves to `cwd/.claude`, so an unvalidated name can point the hard-delete
|
|
29
|
-
* at the shared `.claude/` install (or anything else relative to cwd). Gated
|
|
30
|
-
* by `isValidFeatureName` (same kebab-slug rule `create` stamps at birth) PLUS
|
|
31
|
-
* a resolved-path containment assert — validated by path, not by the
|
|
32
|
-
* convention that a real feature name never contains `..`.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
/** Refuse a delete/archive whose resolved target escapes `.morph/features/{scope}/{name}`. */
|
|
9
|
+
// `featureName` flows into a recursive rmSync and `../../.claude` would resolve to the shared
|
|
10
|
+
// install: the name is validated AND the resolved path must stay contained. Dropping the root
|
|
11
|
+
// index entry matters too, or the next loadState resurrects the folder.
|
|
12
|
+
|
|
36
13
|
function assertContained(scopeDir, name, target) {
|
|
37
14
|
const scopeAbs = resolve(scopeDir) + sep;
|
|
38
15
|
const targetAbs = resolve(target);
|
|
@@ -57,7 +34,6 @@ function approvedGates(feature) {
|
|
|
57
34
|
.map(([name]) => name);
|
|
58
35
|
}
|
|
59
36
|
|
|
60
|
-
/** Drop the feature from the thin, derivable root index (like archive does). */
|
|
61
37
|
function dropFromIndex(cwd, featureName) {
|
|
62
38
|
const rootPath = join(cwd, '.morph', 'state.json');
|
|
63
39
|
if (!existsSync(rootPath)) return;
|
|
@@ -76,11 +52,7 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
76
52
|
try {
|
|
77
53
|
const cwd = options.cwd || process.cwd();
|
|
78
54
|
|
|
79
|
-
//
|
|
80
|
-
// traversal attempt (`../../.claude`) never reaches existsSync/rmSync. Same
|
|
81
|
-
// gate `create` stamps at birth and `finish` re-checks; unlike those two,
|
|
82
|
-
// delete/archive take a FRESH argument every invocation, so this cannot rely
|
|
83
|
-
// on "every real feature folder is already a valid slug".
|
|
55
|
+
// Validated BEFORE any path is built: delete takes a fresh argument on every invocation.
|
|
84
56
|
if (!isValidFeatureName(featureName)) {
|
|
85
57
|
console.error(chalk.red(`\n❌ Invalid feature name: "${featureName}"`));
|
|
86
58
|
console.error(chalk.gray('Use kebab-case: lowercase letters, digits and hyphens (e.g. "user-onboarding")\n'));
|
|
@@ -97,14 +69,12 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
97
69
|
process.exit(1);
|
|
98
70
|
}
|
|
99
71
|
|
|
100
|
-
//
|
|
101
|
-
// mutates state has no place inside a delete).
|
|
72
|
+
// Not loadState: a read that mutates state has no place inside a delete.
|
|
102
73
|
let feature = {};
|
|
103
74
|
if (existsSync(fjPath)) {
|
|
104
75
|
try { feature = JSON.parse(readFileSync(fjPath, 'utf8')); } catch { feature = {}; }
|
|
105
76
|
}
|
|
106
77
|
|
|
107
|
-
// Precondition: no approved gate (real work) unless --force.
|
|
108
78
|
const approved = approvedGates(feature);
|
|
109
79
|
if (approved.length && !options.force) {
|
|
110
80
|
console.error(chalk.red(`\n❌ "${featureName}" has approved gate(s): ${approved.join(', ')}.`));
|
|
@@ -113,14 +83,8 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
113
83
|
process.exit(1);
|
|
114
84
|
}
|
|
115
85
|
|
|
116
|
-
// A live worktree
|
|
117
|
-
//
|
|
118
|
-
// (no `no-feature` audit hit either: featureCommittedOnBranch stays true).
|
|
119
|
-
// Distinct consent from --force on purpose: --force answers "approved gate
|
|
120
|
-
// present, delete anyway" (a STATE risk); a live worktree is a FILESYSTEM
|
|
121
|
-
// risk (orphan directory, junctions into the primary root) — the same
|
|
122
|
-
// reasoning that keeps `worktree remove`'s PROVE-or-DECLINE separate from
|
|
123
|
-
// gate policy.
|
|
86
|
+
// A live worktree owns the real state; deleting the root registration would orphan it. A distinct
|
|
87
|
+
// consent from --force on purpose: --force answers a state risk, this one is a filesystem risk.
|
|
124
88
|
const owner = resolveFeatureTree(featureName, cwd);
|
|
125
89
|
const liveElsewhere = (owner.source === 'registry' || owner.source === 'pointer') && owner.tree;
|
|
126
90
|
if (liveElsewhere) {
|
|
@@ -141,14 +105,9 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
141
105
|
process.exit(1);
|
|
142
106
|
}
|
|
143
107
|
|
|
144
|
-
// PROVE-or-DECLINE
|
|
145
|
-
// worktree actually came down. A refusal here must leave EVERYTHING
|
|
146
|
-
// untouched, same contract as `worktree remove`.
|
|
108
|
+
// PROVE-or-DECLINE: a refusal here must leave everything untouched.
|
|
147
109
|
const root = resolvePrimaryRoot(cwd);
|
|
148
|
-
// The
|
|
149
|
-
// comes down BEFORE its worktree: the compose file and the bind mount
|
|
150
|
-
// live there, and a deleted feature has nothing to keep a volume for.
|
|
151
|
-
// Fail-open by contract — a stubborn container never blocks the delete.
|
|
110
|
+
// The stack comes down BEFORE the worktree, where its compose file and bind mount live. Fail-open.
|
|
152
111
|
try {
|
|
153
112
|
tearDownFeatureStack(featureName, { root, worktreePath: owner.tree, volumes: true });
|
|
154
113
|
} catch { /* fail-open */ }
|
|
@@ -166,15 +125,11 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
166
125
|
console.error(chalk.gray(` ${teardown.declineReason || 'motivo desconhecido'}\n`));
|
|
167
126
|
process.exit(1);
|
|
168
127
|
}
|
|
169
|
-
// Fall through: the feature's own .morph/features/{featureName} copy in
|
|
170
|
-
// `cwd` (the primary root, by construction of `liveElsewhere`) is deleted
|
|
171
|
-
// by the normal flow below, exactly as if there had never been a worktree.
|
|
172
128
|
}
|
|
173
129
|
|
|
174
130
|
const useGit = isGitRepo(cwd) && options.git !== false;
|
|
175
131
|
|
|
176
132
|
if (options.archive) {
|
|
177
|
-
// Soft delete: move to .morph/archive with status "abandoned".
|
|
178
133
|
const archiveDir = join(cwd, '.morph', 'archive');
|
|
179
134
|
const archivePath = join(archiveDir, featureName);
|
|
180
135
|
if (existsSync(archivePath)) {
|
|
@@ -209,7 +164,6 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
209
164
|
process.exit(0);
|
|
210
165
|
}
|
|
211
166
|
|
|
212
|
-
// Hard delete: remove the folder (git-aware), then drop from index.
|
|
213
167
|
let staged = false;
|
|
214
168
|
if (useGit) {
|
|
215
169
|
try {
|
|
@@ -218,13 +172,7 @@ export async function deleteCommand(featureName, options = {}) {
|
|
|
218
172
|
} catch {
|
|
219
173
|
// Untracked (never committed) — nothing for git rm to act on.
|
|
220
174
|
}
|
|
221
|
-
// `git rm` only
|
|
222
|
-
// with no artifact in it (0-proposal/ with nothing written yet) has no
|
|
223
|
-
// tracked blob and survives as an empty directory on disk. This bit
|
|
224
|
-
// real after --with-worktree: teardownWorktree's own registration-clear
|
|
225
|
-
// commits the root's feature.json on its way through, so `git rm`
|
|
226
|
-
// SUCCEEDS on that one file while the sibling empty folders it never
|
|
227
|
-
// tracked are left behind. Unconditional sweep closes both paths at once.
|
|
175
|
+
// `git rm` only removes tracked files: scaffolded empty phase folders survive it.
|
|
228
176
|
if (existsSync(featuresPath)) rmSync(featuresPath, { recursive: true, force: true });
|
|
229
177
|
try { execSync(`git add -A "${featuresPath}"`, { cwd, stdio: 'pipe' }); staged = true; } catch { /* not fatal */ }
|
|
230
178
|
} else {
|