@polymorphism-tech/morph-spec 8.47.0 → 9.0.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 +48 -39
- package/README.md +3 -4
- package/bin/morph-spec.js +37 -51
- package/bin/validate.js +3 -111
- 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 +75 -18
- 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-proposal.md +2 -50
- package/framework/commands/morph-status.md +3 -3
- package/framework/docs/CLI.md +585 -286
- package/framework/evals/review-checklist.md +82 -41
- package/framework/hooks/README.md +10 -11
- package/framework/hooks/claude-code/core/comment-guard.js +1 -1
- package/framework/hooks/claude-code/core/denylist.json +33 -3
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +16 -20
- package/framework/hooks/claude-code/core/gate-guard.js +2 -11
- package/framework/hooks/claude-code/core/pre-bash-denylist.js +38 -0
- package/framework/hooks/claude-code/core/protect-spec-files.js +30 -242
- package/framework/hooks/claude-code/core/state-sync.js +7 -21
- package/framework/hooks/claude-code/core/telemetry-log.js +3 -3
- package/framework/hooks/claude-code/core/validate-completion.js +33 -97
- package/framework/hooks/claude-code/core/warn-bash-source-write.js +31 -0
- package/framework/hooks/claude-code/core/worktree-context.js +5 -4
- package/framework/hooks/claude-code/statusline.py +55 -41
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/shared/activity-logger.js +1 -1
- package/framework/hooks/shared/build-check.js +10 -6
- package/framework/hooks/shared/command-tokens.js +169 -0
- package/framework/hooks/shared/comment-rules.js +1 -1
- package/framework/hooks/shared/comment-scanner.js +10 -23
- package/framework/hooks/shared/comment-stripper.js +1 -1
- package/framework/hooks/shared/e2e-check.js +64 -27
- package/framework/hooks/shared/errata.js +72 -0
- package/framework/hooks/shared/feature-locator.js +1 -1
- package/framework/hooks/shared/frontend-locations.js +6 -0
- package/framework/hooks/shared/gate-question.js +18 -0
- package/framework/hooks/shared/phase-utils.js +15 -32
- package/framework/hooks/shared/slice-progress.js +118 -0
- package/framework/hooks/shared/spawn-command.js +23 -0
- package/framework/hooks/shared/state-reader.js +61 -87
- package/framework/hooks/shared/state-writer.js +2 -3
- package/framework/mcp/registry.json +3 -4
- package/framework/phases.json +23 -39
- 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 +77 -152
- package/framework/standards/STANDARDS.json +86 -1218
- package/framework/standards/STANDARDS.meta.json +1305 -0
- package/framework/standards/ai-agents/evals-with-cache.md +1 -2
- package/framework/standards/ai-agents/setup.md +1 -1
- package/framework/standards/architecture/code-comments.md +6 -6
- package/framework/standards/integration/mcp/mcp-tools.md +7 -7
- package/framework/templates/README.md +2 -3
- package/framework/templates/REGISTRY.json +6 -170
- package/framework/templates/docs/plan.md +72 -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/e2e/e2e.js +2 -2
- package/src/commands/observability/cost.js +18 -60
- package/src/commands/project/doctor-procs.js +1 -1
- package/src/commands/project/doctor.js +9 -9
- package/src/commands/project/fleet.js +4 -4
- package/src/commands/project/heavy.js +3 -3
- package/src/commands/project/init.js +4 -0
- 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 +79 -25
- package/src/commands/project/status.js +29 -69
- package/src/commands/project/update.js +17 -1
- package/src/commands/project/worktree.js +1 -1
- package/src/commands/state/advance.js +62 -46
- package/src/commands/state/approve.js +81 -141
- package/src/commands/state/archive.js +20 -84
- package/src/commands/state/auto-approval.js +68 -0
- package/src/commands/state/create.js +28 -1
- package/src/commands/state/delete.js +1 -1
- package/src/commands/state/finish.js +11 -23
- package/src/commands/state/gate-check.js +85 -84
- package/src/commands/state/gate-decision.js +6 -4
- package/src/commands/state/handoff.js +1 -1
- package/src/commands/state/list.js +9 -9
- package/src/commands/state/report-check.js +157 -311
- package/src/commands/state/retype.js +9 -3
- package/src/commands/validation/mutate.js +77 -14
- package/src/commands/validation/plan-check.js +81 -0
- package/src/commands/validation/validate-feature.js +60 -135
- package/src/commands/validation/verify.js +40 -72
- package/src/core/paths/output-schema.js +19 -66
- package/src/core/state/gate-order.js +5 -6
- package/src/core/state/lifecycle-audit.js +2 -2
- package/src/core/state/state-manager.js +17 -98
- package/src/core/templates/template-registry.js +2 -2
- package/src/core/templates/template-seed.js +22 -0
- package/src/core/work-types.js +10 -10
- package/src/dashboard/app/components/ActivityFeed.jsx +2 -3
- package/src/dashboard/app/components/CommandPalette.jsx +5 -5
- package/src/dashboard/app/components/EntityLink.jsx +1 -1
- package/src/dashboard/app/hooks/useMorphQuery.js +1 -1
- package/src/dashboard/app/lib/phases.js +2 -4
- package/src/dashboard/app/pages/Activity.jsx +1 -1
- package/src/dashboard/app/pages/FeatureDetail.jsx +139 -129
- package/src/dashboard/app/pages/Features.jsx +9 -9
- package/src/dashboard/app/pages/Guide.jsx +2 -2
- package/src/dashboard/app/pages/PhasePipeline.jsx +3 -4
- package/src/dashboard/app/pages/Standards.jsx +1 -1
- package/src/dashboard/scanner/activity-scanner.js +5 -15
- package/src/dashboard/scanner/agents-scanner.js +1 -1
- package/src/dashboard/scanner/docs-scanner.js +2 -2
- package/src/dashboard/scanner/features-scanner.js +95 -60
- package/src/dashboard/scanner/project-api.js +1 -1
- package/src/dashboard/scanner/standards-scanner.js +2 -1
- package/src/lib/ci/ci-verify.js +17 -1
- package/src/lib/ci/github-ci.js +1 -1
- package/src/lib/detectors/index.js +3 -8
- package/src/lib/generators/handoff-generator.js +34 -65
- package/src/lib/generators/settings-generator.js +11 -89
- package/src/lib/git/evidence-staleness.js +1 -1
- package/src/lib/git/tree-fingerprint.js +19 -7
- package/src/lib/git/tree-state.js +2 -2
- package/src/lib/heavy/cleanup.js +1 -5
- package/src/lib/installers/memory-installer.js +6 -8
- package/src/lib/mutation/commands.js +3 -2
- package/src/lib/{tasks/dotnet-test-introspection.js → mutation/dotnet-introspection.js} +17 -282
- package/src/lib/mutation/plan.js +14 -6
- package/src/lib/mutation/runner.js +1 -1
- package/src/lib/mutation/subset.js +46 -9
- package/src/lib/plan/artifact-vocabulary.js +60 -0
- package/src/lib/plan/checks.js +234 -0
- package/src/lib/plan/plan-parser.js +209 -0
- package/src/lib/plan/plan-template.js +18 -0
- package/src/lib/review-reports.js +222 -0
- package/src/lib/risk-detector.js +131 -140
- package/src/lib/specs/adr-index.js +50 -69
- package/src/lib/specs/design-seed.js +18 -0
- package/src/lib/specs/frontmatter.js +44 -0
- package/src/lib/specs/gfm-table.js +17 -0
- package/src/lib/specs/old-format.js +68 -0
- package/src/lib/specs/revocations.js +37 -95
- package/src/lib/specs/screen-checklist.js +18 -17
- package/src/lib/stack/dotnet-build-ignores.js +47 -0
- package/src/lib/stack/stack-scan.js +267 -0
- package/src/lib/standards/registry.js +43 -0
- package/src/lib/standards/sections.js +58 -0
- package/src/lib/tasks/eval-node.js +4 -12
- package/src/lib/tasks/test-nodes.js +1 -74
- package/src/lib/tasks/test-runner.js +75 -117
- package/src/lib/telemetry/metrics.js +8 -69
- package/src/lib/telemetry/telemetry-reader.js +5 -118
- package/src/lib/telemetry/verify-event.js +5 -7
- package/src/lib/validators/code-budget/code-budget-validator.js +1 -1
- package/src/lib/validators/contracts/contract-compliance-validator.js +2 -2
- package/src/lib/validators/reuse/reuse-validator.js +22 -45
- package/src/lib/validators/traceability-check.js +85 -129
- package/src/lib/validators/verify-runner.js +118 -235
- package/src/lib/worktree/docker-audit.js +1 -2
- package/src/lib/worktree/fleet-scanner.js +25 -38
- package/src/scripts/setup-infra.js +9 -0
- package/src/utils/agents-installer.js +76 -9
- package/src/utils/claude-settings-manager.js +0 -35
- package/src/utils/file-copier.js +27 -1
- package/src/utils/hooks-installer.js +16 -9
- package/src/utils/skills-installer.js +1 -2
- 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/lib/agents/output-collector.js +0 -76
- package/src/lib/evaluator-report.js +0 -104
- 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/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/bin/morph-spec.js
CHANGED
|
@@ -45,6 +45,8 @@ const claimCommand = lazy('../src/commands/project/claim.js', 'claimCommand');
|
|
|
45
45
|
const standardsCommand = lazy('../src/commands/project/standards.js', 'standardsCommand');
|
|
46
46
|
const reportCheckCommand = lazy('../src/commands/state/report-check.js', 'reportCheckCommand');
|
|
47
47
|
const scoutCheckCommand = lazy('../src/commands/validation/scout-check.js', 'scoutCheckCommand');
|
|
48
|
+
const planCheckCommand = lazy('../src/commands/validation/plan-check.js', 'planCheckCommand');
|
|
49
|
+
const stackScanCommand = lazy('../src/commands/project/stack-scan.js', 'stackScanCommand');
|
|
48
50
|
|
|
49
51
|
// === Approval gates (human-only) ===
|
|
50
52
|
const approveCommand = lazy('../src/commands/state/approve.js', 'approveCommand');
|
|
@@ -60,11 +62,8 @@ const retypeCommand = lazy('../src/commands/state/retype.js', 'retypeCommand');
|
|
|
60
62
|
const handoffCommand = lazy('../src/commands/state/handoff.js', 'handoffCommand');
|
|
61
63
|
const listCommand = lazy('../src/commands/state/list.js', 'listCommand');
|
|
62
64
|
const deleteCommand = lazy('../src/commands/state/delete.js', 'deleteCommand');
|
|
63
|
-
const usecaseReserveCommand = lazy('../src/commands/state/usecase.js', 'usecaseReserveCommand');
|
|
64
|
-
const usecaseCheckCommand = lazy('../src/commands/state/usecase.js', 'usecaseCheckCommand');
|
|
65
65
|
|
|
66
66
|
// === Tasks ===
|
|
67
|
-
const dagCommand = lazy('../src/commands/tasks/dag.js', 'dagCommand');
|
|
68
67
|
|
|
69
68
|
// === Codebase graph ===
|
|
70
69
|
const graphStatusCommand = lazy('../src/commands/graph/status.js', 'graphStatusCommand');
|
|
@@ -174,7 +173,7 @@ program
|
|
|
174
173
|
|
|
175
174
|
program
|
|
176
175
|
.command('list')
|
|
177
|
-
.description('List every feature × status × gates (G1/
|
|
176
|
+
.description('List every feature × status × gates (G1 plan / Gd uiux / G3 review) × workType — the audit board')
|
|
178
177
|
.option('--all', 'Include archived features (.morph/archive)')
|
|
179
178
|
.option('--archived', 'Include archived features (alias of --all)')
|
|
180
179
|
.option('--no-branch', 'Skip reading morph/{feature} for truth — report only what is on disk in this tree')
|
|
@@ -184,12 +183,12 @@ program
|
|
|
184
183
|
// ─── Approval gates (dev-only) ────────────────────────────────────────────
|
|
185
184
|
program
|
|
186
185
|
.command('approve <feature> <gate>')
|
|
187
|
-
.description('Approve a phase gate (
|
|
186
|
+
.description('Approve a phase gate (plan, uiux, review). Enforces gate order (uiux and review require plan)')
|
|
188
187
|
.option('--approver <name>', 'Name of approver (default: current user when interactive, "auto" otherwise)')
|
|
189
188
|
.option('--mode <mode>', 'Approval mode: "user" or "auto" (default: detected from TTY)')
|
|
190
189
|
.option('--notes <notes>', 'Approval notes')
|
|
191
190
|
.option('--force', 'Approve out of order (bypass the gate-monotonicity check)')
|
|
192
|
-
.option('--self-assessed', 'Gate 3 only: approve without
|
|
191
|
+
.option('--self-assessed', 'Gate 3 only: approve without the review reports (verifier.md, reviewer.md, security.md), recording the degradation in feature.json')
|
|
193
192
|
.action((feature, gate, options) => approveCommand(feature, gate, options));
|
|
194
193
|
|
|
195
194
|
program
|
|
@@ -197,7 +196,7 @@ program
|
|
|
197
196
|
.description('Approve the current phase gate and scaffold the next phase folder (one step)')
|
|
198
197
|
.option('--approver <name>', 'Name of approver (default: current user when interactive, "auto" otherwise)')
|
|
199
198
|
.option('--mode <mode>', 'Approval mode: "user" or "auto" (default: detected from TTY)')
|
|
200
|
-
.option('--design', 'From
|
|
199
|
+
.option('--design', 'From plan, advance into the optional design (uiux) phase instead of implement')
|
|
201
200
|
.option('--notes <notes>', 'Approval notes')
|
|
202
201
|
.option('--force', 'Advance even if a prerequisite gate is unapproved (out-of-order recovery)')
|
|
203
202
|
.action((feature, options) => advanceCommand(feature, options));
|
|
@@ -251,7 +250,7 @@ program
|
|
|
251
250
|
program
|
|
252
251
|
.command('gate-check <feature> <gate>')
|
|
253
252
|
.description('Decide + record a gate\'s trust decision from disk-derived signals (shouldPauseGate) — the deterministic default; see gate-decision for the manual escape hatch')
|
|
254
|
-
.option('--signals <json>', 'Override ONLY standardsViolations/designSystemDivergence (not derivable from disk) — everything else is read from feature.json/
|
|
253
|
+
.option('--signals <json>', 'Override ONLY standardsViolations/designSystemDivergence (not derivable from disk) — everything else is read from feature.json/checks.json/git and cannot be overridden here')
|
|
255
254
|
.option('--trust <mode>', 'Trust mode to decide with (default: config.json → trust, or "auto")')
|
|
256
255
|
.option('--json', 'Output as JSON')
|
|
257
256
|
.action((feature, gateArg, options) => gateCheckCommand(feature, gateArg, options));
|
|
@@ -294,33 +293,6 @@ program
|
|
|
294
293
|
.option('--here', 'Force building/writing in the current directory, even if another tree owns this feature')
|
|
295
294
|
.action((feature, options) => handoffCommand(feature, options));
|
|
296
295
|
|
|
297
|
-
// ─── Use cases ────────────────────────────────────────────────────────────
|
|
298
|
-
const usecaseCommand = program
|
|
299
|
-
.command('usecase')
|
|
300
|
-
.description('Project-wide use cases: UC-{nn} numbering (acervo + every worktree of this repo) and the acervo lifecycle check');
|
|
301
|
-
|
|
302
|
-
usecaseCommand
|
|
303
|
-
.command('reserve')
|
|
304
|
-
.description('Atomically reserve the next N UC-{nn} numbers, shared across every worktree of this repo — replaces the old max+1 disk scan, which collides across worktrees')
|
|
305
|
-
.option('--count <n>', 'How many numbers to reserve', '1')
|
|
306
|
-
.option('--feature <name>', 'Feature to record as the reservation owner (defaults to the sole active feature, if unambiguous) — also what the promotion collision guard compares against')
|
|
307
|
-
.option('--json', 'Output as JSON')
|
|
308
|
-
.action((options) => usecaseReserveCommand(options));
|
|
309
|
-
|
|
310
|
-
usecaseCommand
|
|
311
|
-
.command('check <feature>')
|
|
312
|
-
.description('Check a feature against the acervo lifecycle: tasks citing a superseded UC, malformed supersession frontmatter, spec.md revocation rows the finish could not apply (plus the task/use-case plumbing dag checks, when tasks.json exists)')
|
|
313
|
-
.option('--json', 'Output as JSON')
|
|
314
|
-
.action((feature, options) => usecaseCheckCommand(feature, options));
|
|
315
|
-
|
|
316
|
-
// ─── Tasks ────────────────────────────────────────────────────────────────
|
|
317
|
-
program
|
|
318
|
-
.command('dag <feature>')
|
|
319
|
-
.description('Analyze the tasks.json DAG and print the sequential vs parallel dispatch decision (effort-weighted)')
|
|
320
|
-
.option('--json', 'Output as JSON')
|
|
321
|
-
.option('--mermaid', 'Emit the tasks.json DAG as a Mermaid flowchart (flowchart TD)')
|
|
322
|
-
.action((feature, options) => dagCommand(feature, options));
|
|
323
|
-
|
|
324
296
|
// ─── Codebase graph ───────────────────────────────────────────────────────
|
|
325
297
|
const graphCommand = program
|
|
326
298
|
.command('graph')
|
|
@@ -388,24 +360,23 @@ program
|
|
|
388
360
|
.action(validateFeatureCommand);
|
|
389
361
|
|
|
390
362
|
program
|
|
391
|
-
.command('verify <feature>
|
|
363
|
+
.command('verify <feature>')
|
|
392
364
|
.description('Run the deterministic verification chain (build + tests + validators + e2e) — code before the LLM judge')
|
|
393
365
|
.option('--json', 'Output as JSON')
|
|
394
366
|
.option('--timeout <ms>', 'Timeout in ms for the build AND tests nodes (build default 120000; tests default 120000 per test project, or project.testTimeoutMs)', (v) => parseInt(v, 10))
|
|
395
367
|
.option('--filter <ids>', 'Run only the test nodes whose id matches (comma-separated; exact or substring). Unmatched nodes are reported as skip; matching nothing is a usage error (exit 2)')
|
|
396
368
|
.option('--linux', 'Run the test nodes inside a Linux container, on a COPY of the tree (the host tree is mounted read-only and copied in — a bind mount is case-insensitive and cannot reproduce case defects). No Docker = usage error, never a skip')
|
|
397
369
|
.option('--linux-image <img>', 'Image used by --linux (default: mcr.microsoft.com/dotnet/sdk:10.0)')
|
|
398
|
-
.option('--
|
|
399
|
-
.option('--record-baseline', 'Measure every test node and write expectedCount back into .morph/config/config.json (only from an all-green run at FEATURE scope; with a task id it is a usage error; never creates config.json)')
|
|
370
|
+
.option('--record-baseline', 'Measure every test node and write expectedCount back into .morph/config/config.json (only from an all-green run; never creates config.json)')
|
|
400
371
|
.option('--refresh-cache', 'Rewrite the response cache of every `runner: "evals"` node against the real provider. NEVER implicit: a cache rewrite is a paid call nobody asked for. Requires the declared envFile; no eval node declared, --skip-tests, or a --filter that excludes them all are usage errors (exit 2), refused BEFORE the cache is touched')
|
|
401
|
-
.option('--skip-tests', 'Skip the test node.
|
|
402
|
-
.option('--skip-build', 'Skip the build node.
|
|
372
|
+
.option('--skip-tests', 'Skip the test node. The run is partial, so the verification stamp is NOT written (reason "skip-tests")')
|
|
373
|
+
.option('--skip-build', 'Skip the build node. The run is partial, so the verification stamp is NOT written (reason "skip-build")')
|
|
403
374
|
.option('--skip-e2e', 'Skip the e2e node (Docker bring-up + Playwright)')
|
|
404
375
|
.option('--fresh-e2e', 'Recreate the e2e stack from scratch: down -v (named volumes included), drop the freshness stamp, rebuild, re-seed auth')
|
|
405
376
|
.option('--no-persist', 'Do not persist the result to feature.json')
|
|
406
|
-
.option('--ci', '
|
|
407
|
-
.action((feature,
|
|
408
|
-
verifyCommand(feature,
|
|
377
|
+
.option('--ci', 'Push morph/<feature> and take the proof from the project CI (creates .github/workflows/morph-verify.yml when no workflow runs verify). Same stamp, source "ci". No GitHub/gh/workflow = local verify with the reason; uncommitted code = exit 2; CI still running after 50 min = exit 3, no stamp')
|
|
378
|
+
.action((feature, options) =>
|
|
379
|
+
verifyCommand(feature, { ...options, noPersist: options.persist === false })
|
|
409
380
|
);
|
|
410
381
|
|
|
411
382
|
program
|
|
@@ -616,8 +587,9 @@ program
|
|
|
616
587
|
// ─── Standards search (server-side, R2 token cut) ─────────────────────────
|
|
617
588
|
program
|
|
618
589
|
.command('standards')
|
|
619
|
-
.description('Search STANDARDS.json server-side (top 3,
|
|
590
|
+
.description('Search STANDARDS.json server-side (top 3, digest + anchors) or print one section, instead of reading the whole registry. Bare: categories + counts')
|
|
620
591
|
.option('--find <query>', 'Search query — matches name/id, tags/aliases, category, digest')
|
|
592
|
+
.option('--show <target>', '<id>: digest + anchors; <id>#<anchor>: only that section of the standard .md')
|
|
621
593
|
.option('--category <category>', 'Restrict --find to a single category')
|
|
622
594
|
.option('--tags <tags>', 'Restrict --find to standards carrying any of these comma-separated tags')
|
|
623
595
|
.option('--json', 'Output as JSON')
|
|
@@ -625,11 +597,11 @@ program
|
|
|
625
597
|
|
|
626
598
|
// ─── Sub-agent report protocol ────────────────────────────────────────────
|
|
627
599
|
program
|
|
628
|
-
.command('report-check <feature> [
|
|
629
|
-
.description('Audit
|
|
630
|
-
.option('--before-eval', 'Save a snapshot of the tree before dispatching the
|
|
600
|
+
.command('report-check <feature> [slices...]')
|
|
601
|
+
.description('Audit slice report files (3-implement/reports/{slice}.md) against the work the dispatch actually wrote (telemetry, keyed by the agent that wrote the report). Exits 0 only when every audited slice is intact; naming slices audits only those')
|
|
602
|
+
.option('--before-eval', 'Save a snapshot of the tree before dispatching the review agents and print their models; later runs report what changed since')
|
|
631
603
|
.option('--json', 'Output as JSON')
|
|
632
|
-
.action((feature,
|
|
604
|
+
.action((feature, slices, options) => reportCheckCommand(feature, slices, options));
|
|
633
605
|
|
|
634
606
|
program
|
|
635
607
|
.command('scout-check <map>')
|
|
@@ -638,6 +610,20 @@ program
|
|
|
638
610
|
.option('--json', 'Output as JSON')
|
|
639
611
|
.action((map, options) => scoutCheckCommand(map, options));
|
|
640
612
|
|
|
613
|
+
program
|
|
614
|
+
.command('plan-check <feature>')
|
|
615
|
+
.description('Parse 2-plan/plan.md (scenarios, slices, decisions, reuse) and, with no error, write 2-plan/checks.json — the only writer of checks.json. Refuses to rewrite it once the plan gate is approved and the plan changed outside ## Errata. Exits 1 on errors, 2 when plan.md is missing')
|
|
616
|
+
.option('--json', 'Output as JSON')
|
|
617
|
+
.addHelpText('after', () => '\nGramática (framework/templates/docs/plan.md):\n\n' +
|
|
618
|
+
readFileSync(join(__dirname, '..', 'framework', 'templates', 'docs', 'plan.md'), 'utf8').replace(/\{\{FEATURE_NAME\}\}/g, '<feature>'))
|
|
619
|
+
.action((feature, options) => planCheckCommand(feature, options));
|
|
620
|
+
|
|
621
|
+
program
|
|
622
|
+
.command('stack-scan [feature]')
|
|
623
|
+
.description('Audit the code against config.project.stack, judging only the configured stacks (runtime, ORM, database, Guid.NewGuid, generic repository, service layer, raw SQL, sealed, router, UI library) by severity. With a feature, write .morph/features/<f>/2-plan/stack-scan.md; without, print the report')
|
|
624
|
+
.option('--json', 'Output as JSON')
|
|
625
|
+
.action((feature, options) => stackScanCommand(feature, options));
|
|
626
|
+
|
|
641
627
|
// ─── Dashboard ────────────────────────────────────────────────────────────
|
|
642
628
|
program
|
|
643
629
|
.command('dashboard')
|
|
@@ -657,10 +643,10 @@ program
|
|
|
657
643
|
|
|
658
644
|
program
|
|
659
645
|
.command('cost [feature]')
|
|
660
|
-
.description('Cost-facing view over .morph/logs/events.jsonl:
|
|
661
|
-
.option('--by <mode>', 'Group by:
|
|
646
|
+
.description('Cost-facing view over .morph/logs/events.jsonl: bytes re-ingested by kind (proxy, not tokens), dispatch counts, real tokens when observed')
|
|
647
|
+
.option('--by <mode>', 'Group by: phase (default: feature-wide summary; with --all-trees, applies to the combined aggregate)')
|
|
662
648
|
.option('--all-trees', 'Aggregate across every git worktree with a log plus the logs finish saved in .git/morph-spec/finish-backup — per-tree breakdown + combined total')
|
|
663
|
-
.option('--metrics', 'Loop measurements: turns, tool calls (orchestrator x sub-agent), time per command class, identical reruns, rereads,
|
|
649
|
+
.option('--metrics', 'Loop measurements: turns, tool calls (orchestrator x sub-agent), time per command class, identical reruns, rereads, verify count per feature, git calls, reuse validator per tree')
|
|
664
650
|
.option('--top <n>', 'With --metrics: how many reread files to list (default 10)', (v) => Number.parseInt(v, 10))
|
|
665
651
|
.option('--json', 'Output the aggregate as JSON')
|
|
666
652
|
.action((feature, options) => costCommand(feature, options));
|
package/bin/validate.js
CHANGED
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Runs validators for the current project stack (detected from .morph/config/config.json).
|
|
7
7
|
*
|
|
8
|
-
* .NET stacks: packages
|
|
9
|
-
* Next.js stack: next-components
|
|
10
|
-
* Other stacks: spec-tasks
|
|
8
|
+
* .NET stacks: packages
|
|
9
|
+
* Next.js stack: next-components
|
|
11
10
|
*
|
|
12
11
|
* Usage:
|
|
13
12
|
* morph-spec validate [options]
|
|
@@ -21,12 +20,7 @@
|
|
|
21
20
|
import chalk from 'chalk';
|
|
22
21
|
import { getStackProfile } from '../src/lib/stack/stack-profile.js';
|
|
23
22
|
|
|
24
|
-
/**
|
|
25
|
-
* Build the VALIDATORS registry for the current stack.
|
|
26
|
-
* .NET stacks → packages, spec-tasks
|
|
27
|
-
* nextjs stack → next-components, spec-tasks
|
|
28
|
-
* other stacks → spec-tasks only
|
|
29
|
-
*/
|
|
23
|
+
/** The validators of the current stack: .NET → packages, Next.js → next-components. */
|
|
30
24
|
async function buildValidators(stack) {
|
|
31
25
|
const validators = {};
|
|
32
26
|
|
|
@@ -52,111 +46,9 @@ async function buildValidators(stack) {
|
|
|
52
46
|
};
|
|
53
47
|
}
|
|
54
48
|
|
|
55
|
-
validators['spec-tasks'] = {
|
|
56
|
-
name: 'Spec vs Tasks Coverage',
|
|
57
|
-
description: 'Validates that tasks.json covers all requirements from spec.md',
|
|
58
|
-
run: validateSpecVsTasks
|
|
59
|
-
};
|
|
60
|
-
|
|
61
49
|
return validators;
|
|
62
50
|
}
|
|
63
51
|
|
|
64
|
-
/**
|
|
65
|
-
* Validate spec.md requirements are covered by tasks
|
|
66
|
-
*/
|
|
67
|
-
async function validateSpecVsTasks(projectPath, options = {}) {
|
|
68
|
-
const path = await import('path');
|
|
69
|
-
const fs = await import('fs');
|
|
70
|
-
const { loadState } = await import('../src/core/state/state-manager.js');
|
|
71
|
-
|
|
72
|
-
const results = [];
|
|
73
|
-
let errors = 0;
|
|
74
|
-
let warnings = 0;
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
const state = loadState(false);
|
|
78
|
-
if (!state || !state.features) {
|
|
79
|
-
return { status: 'ok', errors: 0, warnings: 0, message: 'No features to validate' };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
for (const [featureName, feature] of Object.entries(state.features)) {
|
|
83
|
-
const outputsPath = path.join(projectPath, '.morph/features', featureName);
|
|
84
|
-
const specPath = path.join(outputsPath, 'spec.md');
|
|
85
|
-
|
|
86
|
-
if (!fs.existsSync(specPath)) {
|
|
87
|
-
continue; // No spec to validate
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Read spec.md and extract requirements
|
|
91
|
-
const specContent = fs.readFileSync(specPath, 'utf-8');
|
|
92
|
-
|
|
93
|
-
// Extract requirement patterns (## Requisitos, - [ ], numbered lists, etc.)
|
|
94
|
-
const requirementPatterns = [
|
|
95
|
-
/^#+\s*Requisitos?\s*$/gim,
|
|
96
|
-
/^-\s*\[.\]\s*(.+)$/gm,
|
|
97
|
-
/^\d+\.\s+(.+)$/gm
|
|
98
|
-
];
|
|
99
|
-
|
|
100
|
-
const requirements = [];
|
|
101
|
-
for (const pattern of requirementPatterns) {
|
|
102
|
-
const matches = specContent.matchAll(pattern);
|
|
103
|
-
for (const match of matches) {
|
|
104
|
-
if (match[1]) {
|
|
105
|
-
requirements.push(match[1].trim());
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Check if feature has tasks
|
|
111
|
-
if (!feature.tasks || (Array.isArray(feature.tasks) && feature.tasks.length === 0)) {
|
|
112
|
-
if (requirements.length > 0) {
|
|
113
|
-
warnings++;
|
|
114
|
-
results.push({
|
|
115
|
-
feature: featureName,
|
|
116
|
-
level: 'warning',
|
|
117
|
-
message: `Spec has ${requirements.length} requirements but no tasks defined`
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Get task titles
|
|
124
|
-
const taskTitles = Array.isArray(feature.tasks)
|
|
125
|
-
? feature.tasks.map(t => t.title?.toLowerCase() || '')
|
|
126
|
-
: [];
|
|
127
|
-
|
|
128
|
-
// Check each requirement has a matching task (fuzzy match)
|
|
129
|
-
for (const req of requirements.slice(0, 20)) { // Limit to first 20
|
|
130
|
-
const reqLower = req.toLowerCase();
|
|
131
|
-
const hasMatch = taskTitles.some(title =>
|
|
132
|
-
title.includes(reqLower.slice(0, 20)) ||
|
|
133
|
-
reqLower.includes(title.slice(0, 20))
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (!hasMatch && options.verbose) {
|
|
137
|
-
console.log(chalk.gray(` ? Requirement may not be covered: "${req.slice(0, 50)}..."`));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (options.verbose) {
|
|
142
|
-
console.log(chalk.green(` ✓ ${featureName}: ${requirements.length} requirements, ${taskTitles.length} tasks`));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
} catch (error) {
|
|
147
|
-
if (options.verbose) {
|
|
148
|
-
console.log(chalk.yellow(` ⚠ Could not validate: ${error.message}`));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
status: errors > 0 ? 'error' : warnings > 0 ? 'warning' : 'ok',
|
|
154
|
-
errors,
|
|
155
|
-
warnings,
|
|
156
|
-
results
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
52
|
/**
|
|
161
53
|
* Main validation command
|
|
162
54
|
*/
|
package/claude-plugin.json
CHANGED
package/docs/CHEATSHEET.md
CHANGED
package/docs/QUICKSTART.md
CHANGED
package/framework/CLAUDE.md
CHANGED
|
@@ -1,114 +1,54 @@
|
|
|
1
1
|
# MORPH-SPEC Runtime Instructions
|
|
2
2
|
|
|
3
|
-
> by Polymorphism Tech —
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
1. Leia `.morph/framework/MORPH.md`
|
|
8
|
-
2.
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
3
|
+
> by Polymorphism Tech — harness spec-driven para Claude Code
|
|
4
|
+
|
|
5
|
+
## Início de cada sessão
|
|
6
|
+
|
|
7
|
+
1. Leia `.morph/framework/MORPH.md` uma vez (de novo após `/compact`): papéis, fases, gates, dispatch.
|
|
8
|
+
2. `.morph/state.json` é índice gitignored, só para achar a feature ativa; o estado autoritativo é `.morph/features/{feature}/feature.json`.
|
|
9
|
+
3. Existe `.morph/features/{feature}/handoff.md`? Leia antes de re-derivar contexto à mão.
|
|
10
|
+
4. Feature em andamento → assuma o papel da fase e continue entre gates sem esperar instrução. Nenhuma ativa → pergunte qual trabalhar.
|
|
11
|
+
|
|
12
|
+
## Regras
|
|
13
|
+
|
|
14
|
+
- Perguntas ao usuário só por `AskUserQuestion` (1-4 por chamada), nunca em texto solto. Na entrevista da `morph-plan`, **uma pergunta por chamada**: lote impede que uma resposta pode os ramos seguintes. Única exceção: ferramenta indisponível ou negada (headless) — texto numerado com a resposta recomendada e gate pausado (`morph-plan` §3).
|
|
15
|
+
- A pergunta de gate nomeia a feature ("Gate do plano — Plano de {feature} aprovado?"): é por esse nome que o hook `state-sync` grava a aprovação no `feature.json` certo; sem nome, com mais de uma feature, ele recusa e você aprova por `morph-spec approve <feature> <gate>`.
|
|
16
|
+
- Estado só pela CLI, nunca à mão: `feature.json`, `gateDecisions`, `checks.json` (escrito só por `plan-check`) e o corpo do `plan.md` depois do gate (fato errado → `## Errata` no fim; escopo mudou → `unapprove`).
|
|
17
|
+
- SessionStart avisou claim vivo de outra sessão na mesma feature → confirme com o usuário antes de `finish`/`archive`/`delete`.
|
|
18
|
+
- Depois de um dispatch, leia o arquivo de relatório da fatia, não a mensagem final, que pode não chegar.
|
|
19
|
+
|
|
20
|
+
## CLI do loop
|
|
21
|
+
|
|
22
|
+
Prefixo `morph-spec`; flags e porquês em `.morph/framework/CLI.md` (um `###` por comando).
|
|
23
|
+
|
|
24
|
+
| Comando | Para quê |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `create <f> --description "…" --type <t> [--worktree]` | nasce a feature; exit 2 = você escolhe o tipo |
|
|
27
|
+
| `stack-scan [f]` | desvios do código contra `project.stack` |
|
|
28
|
+
| `plan-check <f>` | valida `plan.md`, grava `checks.json`, imprime as ondas |
|
|
29
|
+
| `gate-check <f> <gate>` | decide a pausa pelos sinais do disco |
|
|
30
|
+
| `approve <f> <gate> --mode auto` / `advance <f>` | aprova (advance também abre a próxima fase) |
|
|
31
|
+
| `verify <f> [--ci]` | build + testes + validadores + e2e, sem filtro |
|
|
32
|
+
| `report-check <f> [F1 …]` | audita o relatório de cada fatia e diz a ação |
|
|
33
|
+
| `mutate <f>` | mutação dirigida do Gate 3 (até 3 mutantes) |
|
|
34
|
+
| `finish <f> --pr\|--merge` | encerra; só o `--merge` integra |
|
|
35
|
+
| `standards --find "<tema>"` / `--show <id>#<âncora>` | digest do standard / uma seção |
|
|
36
|
+
| `heavy status\|run -- <cmd>` | fila de build/teste; exit 3 = fila cheia |
|
|
37
|
+
| `worktree setup\|provision\|link\|remove\|list\|reap` | ciclo da worktree; `remove` é a única remoção segura |
|
|
38
|
+
| `graph affected\|explain <sym>` | blast radius; sem grafo, caia para grep |
|
|
36
39
|
|
|
37
40
|
## Slash commands
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|---------|-----------|
|
|
41
|
-
| `/morph-proposal {feature}` | Entendimento de negócio + plano (Gates 1 e 2). Passo 0 roteia por tipo de trabalho (`feature`/`bug`/`chore`/`hotfix`) |
|
|
42
|
-
| `/morph-hotfix {feature}` | ADW cirúrgico de hotfix (scout → fix → gate humano → ship) |
|
|
43
|
-
| `/morph-apply {feature}` | Execução autônoma + review (Gate 3) |
|
|
44
|
-
| `/morph-status [feature]` | Status da feature ativa (ou a especificada) |
|
|
45
|
-
| `/morph-archive {feature}` | Arquiva-**sem-integrar** (legadas/faxina) — wrapper de `archive`. Fechamento normal = `finish --pr\|--merge` |
|
|
46
|
-
| `/morph-preflight` | Validação pré-deploy (specs, contratos, testes, infra) |
|
|
47
|
-
| `/morph-troubleshoot [erro]` | Diagnóstico de erros .NET/Next.js com root-cause analysis |
|
|
48
|
-
|
|
49
|
-
**Comandos CLI de gate e de estado** (a LLM os usa em vez de editar o estado à mão):
|
|
50
|
-
|
|
51
|
-
| Comando | Propósito |
|
|
52
|
-
|---------|-----------|
|
|
53
|
-
| `approve <f> <gate> --mode auto` | Aprova gate em `trust:auto`. Gate 3 exige `evaluator-report.md` (ou `--self-assessed`); `hotfix` nunca aceita `--mode auto` — use `--approver` |
|
|
54
|
-
| `advance <f>` | Aprova o gate corrente + já cria a pasta da próxima fase |
|
|
55
|
-
| `gate-check <f> <gate> [--json]` | Default: decide via sinais do disco (`shouldPauseGate`) |
|
|
56
|
-
| `gate-decision <f> <gate> --pause <bool>` | Escape manual: risco que o disco não vê |
|
|
57
|
-
| `create <f> --description "..." --type <t>` | Nasce a feature + `feature.json`; `--worktree` já isola |
|
|
58
|
-
| `list [--all] [--json]` | Quadro de auditoria: feature × workType × status × gates |
|
|
59
|
-
| `delete <f> [--archive] [--force]` | Remove feature; recusa se gate aprovado sem `--force` |
|
|
60
|
-
| `retype <f> <tipo>` | Muda o workType mid-flight; bloqueado após o Gate 3 |
|
|
61
|
-
| `finish <f> --pr\|--merge` | Encerramento único: arquiva, promove use cases, desmonta worktree. Integra só no `--merge`; `--pr` abre PR e fica `aguardando-merge` até alguém mergear |
|
|
62
|
-
| `archive <f>` | Arquiva sem integrar (legadas/faxina) |
|
|
63
|
-
| `worktree setup\|provision\|link\|remove\|list\|reap` | Ciclo do worktree; `provision` = isolamento de task; `remove` é a única remoção segura |
|
|
64
|
-
| `branch prune [--dry-run]` | Apaga branch já integrada, inclusive squash-merge; nunca a com PR aberto |
|
|
65
|
-
| `handoff <f>` | Regenera o documento de retomada da feature |
|
|
66
|
-
| `fleet` | Visão agregada de toda feature ativa (raiz + worktrees) |
|
|
67
|
-
| `claim [f] [--release] [--list]` | Posse advisory — confirme antes de `finish`/`archive`/`delete` se outra sessão tiver claim vivo |
|
|
68
|
-
| `dag <f>` | DAG de `tasks.json`: sequencial/paralelo, recomenda isolamento |
|
|
69
|
-
| `graph status\|build\|refresh` | Grafo de codebase. `status` reporta frescor e se há refresh em background |
|
|
70
|
-
| `graph affected\|explain <sym>` | Blast radius e vizinhança saneados. Sem grafo, caia para grep — nunca é erro |
|
|
71
|
-
| `verify <f> [task] [--ci]` | Build+testes+validadores+e2e — prova da task; a do Gate 3 com `--ci` (no CI) |
|
|
72
|
-
| `e2e up\|status\|down <f>` | Stack de verificação (docker compose) |
|
|
73
|
-
| `doctor --worktrees [--prune]` | Reconcilia git × disco × features; só `--prune` remove algo |
|
|
74
|
-
| `report-check <f> [task...] [--json]` | Audita relatório de sub-agent vs. trabalho entregue |
|
|
75
|
-
| `telemetry [--feature] [--limit]` | Caminho de execução da sessão a partir de `events.jsonl` |
|
|
76
|
-
| `cost [f] [--by task\|phase] [--metrics]` | Custo (bytes/duração) e medições do loop (turnos, rerun, releitura) do mesmo log |
|
|
77
|
-
|
|
78
|
-
Prefixo de todo comando: `morph-spec`. Flags/exemplos: `.morph/framework/CLI.md`.
|
|
79
|
-
|
|
80
|
-
## Skills core (em `.claude/skills/`)
|
|
81
|
-
|
|
82
|
-
| Skill | Quando usar |
|
|
83
|
-
|-------|-------------|
|
|
84
|
-
| `morph-brainstorming` | Entender negócio, escanear stack, produzir proposal.md |
|
|
85
|
-
| `morph-stack-scan` | Desvios de stack em projeto brownfield |
|
|
86
|
-
| `morph-uiux` | Ramo opcional de UI/UX — design system e mockups |
|
|
87
|
-
| `morph-plan` | Destilar use cases e produzir spec.md + tasks.json |
|
|
88
|
-
| `morph-implement` | Executar uma tarefa com auto-advance entre tasks |
|
|
89
|
-
| `morph-review` | Produzir review-report.md (Gate 3) |
|
|
90
|
-
| `morph-hotfix` | Hotfix cirúrgico (`/morph-hotfix`) |
|
|
91
|
-
| `morph-standards` | Localizar standard sob demanda |
|
|
92
|
-
| `morph-machine` | RAM/CPU: fila pesada, órfãos, worktrees sobrando |
|
|
93
|
-
|
|
94
|
-
## Roteamento por tipo de trabalho
|
|
95
|
-
|
|
96
|
-
`workType` (`create --type <tipo>` ou classificado de `--request`) dimensiona o pipeline: `feature` completo (+ ramo uiux quando há superfície de UI), `bug` enxuto, `chore` fast-track (Gates 1/2 por política), `hotfix` scout→fix→gate humano→ship. Canônico: `MORPH.md` §2.1/§5.
|
|
97
|
-
|
|
98
|
-
Features independentes rodam em paralelo, uma por git worktree (`create --worktree`/`worktree setup`), bloco de portas próprio + handoff.md. Fechamento: `finish <f> --pr|--merge`; agregado: `fleet`. Canônico: `MORPH.md` §2.2.
|
|
42
|
+
`/morph-proposal {f}` (plano), `/morph-apply {f}` (execução + Gate 3), `/morph-hotfix {f}`, `/morph-status [f]`.
|
|
99
43
|
|
|
100
44
|
## Personas (em `.claude/agents/`)
|
|
101
45
|
|
|
102
|
-
Despache
|
|
46
|
+
Despache fatias com `subagent_type: "morph-{id}"` — a persona, gerada de `agents.json`, é o system prompt. Tipo não registrado: `general-purpose` com o `persona` colado, registrado no relatório da fatia. Nunca edite `.claude/agents/morph-*.md` à mão (`morph-spec doctor` acusa o drift).
|
|
103
47
|
|
|
104
48
|
<!-- morph-agents:start -->
|
|
105
|
-
_Lista derivada na instalação
|
|
49
|
+
_Lista derivada na instalação. Bloco vazio → `morph-spec setup-infra --reinstall`._
|
|
106
50
|
<!-- morph-agents:end -->
|
|
107
51
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
## Regra de precedência de skills
|
|
111
|
-
|
|
112
|
-
Com o plugin superpowers ativo, `morph-*` vence o equivalente genérico (aplica Gates e paths de `.morph/`), e `using-git-worktrees`→`morph-spec worktree setup|provision`.
|
|
52
|
+
## Precedência de skills
|
|
113
53
|
|
|
114
|
-
|
|
54
|
+
Com o plugin superpowers ativo, `morph-*` vence o equivalente genérico (aplica os gates e os paths de `.morph/`), e `using-git-worktrees`→`morph-spec worktree setup|provision`.
|