@polymorphism-tech/morph-spec 9.7.0 → 10.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.
Files changed (211) hide show
  1. package/CLAUDE.md +11 -11
  2. package/README.md +4 -4
  3. package/bin/morph-spec.js +41 -44
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +24 -30
  8. package/framework/MORPH.md +47 -123
  9. package/framework/agents.json +6 -374
  10. package/framework/commands/morph-apply.md +1 -1
  11. package/framework/commands/morph-archive.md +4 -3
  12. package/framework/commands/morph-hotfix.md +8 -30
  13. package/framework/commands/morph-infra.md +2 -2
  14. package/framework/commands/morph-media.md +10 -9
  15. package/framework/commands/morph-review.md +15 -0
  16. package/framework/commands/morph-status.md +1 -1
  17. package/framework/docs/CLI.md +100 -102
  18. package/framework/evals/review-checklist.md +46 -54
  19. package/framework/hooks/README.md +4 -4
  20. package/framework/hooks/claude-code/__pycache__/statusline.cpython-313.pyc +0 -0
  21. package/framework/hooks/claude-code/core/README.md +1 -1
  22. package/framework/hooks/claude-code/core/denylist.json +4 -4
  23. package/framework/hooks/claude-code/core/gate-guard.js +9 -0
  24. package/framework/hooks/claude-code/core/masked-exit.js +49 -0
  25. package/framework/hooks/claude-code/core/state-sync.js +4 -1
  26. package/framework/hooks/claude-code/core/telemetry-log.js +1 -2
  27. package/framework/hooks/claude-code/core/test-budget.js +10 -70
  28. package/framework/hooks/claude-code/core/validate-completion.js +11 -24
  29. package/framework/hooks/claude-code/core/worktree-context.js +5 -22
  30. package/framework/hooks/claude-code/core/worktree-create.js +6 -45
  31. package/framework/hooks/claude-code/core/worktree-env-inject.js +2 -10
  32. package/framework/hooks/shared/e2e-check.js +0 -0
  33. package/framework/hooks/shared/gate-event.js +2 -2
  34. package/framework/hooks/shared/graph-refresh.js +20 -3
  35. package/framework/hooks/shared/heavy-command.js +32 -1
  36. package/framework/hooks/shared/heavy-config.js +1 -1
  37. package/framework/hooks/shared/heavy-slots.js +41 -4
  38. package/framework/hooks/shared/next-step.js +63 -24
  39. package/framework/hooks/shared/phase-utils.js +6 -9
  40. package/framework/hooks/shared/report-progress.js +86 -0
  41. package/framework/hooks/shared/state-reader.js +3 -2
  42. package/framework/hooks/statusline.js +332 -0
  43. package/framework/phases.json +32 -10
  44. package/framework/rules/ai-agents-standards.md +9 -1
  45. package/framework/rules/csharp-standards.md +4 -0
  46. package/framework/rules/ef-standards.md +20 -0
  47. package/framework/rules/frontend-standards.md +1 -1
  48. package/framework/rules/implement-report.md +25 -0
  49. package/framework/rules/infrastructure-standards.md +2 -0
  50. package/framework/rules/nextjs-standards.md +7 -0
  51. package/framework/rules/plan-grammar.md +53 -0
  52. package/framework/rules/ui-design.md +27 -0
  53. package/framework/schemas/config.schema.json +12 -19
  54. package/framework/schemas/feature.schema.json +7 -1
  55. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  56. package/framework/skills/core/create-umbraco-lp/references/umbraco-lp-patterns.md +1 -1
  57. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +2 -2
  58. package/framework/skills/core/morph-apply/SKILL.md +38 -166
  59. package/framework/skills/core/morph-apply/references/debugging.md +8 -0
  60. package/framework/skills/core/morph-apply/references/hotfix.md +42 -0
  61. package/framework/skills/core/morph-apply/references/machine.md +29 -0
  62. package/framework/skills/core/{morph-media/SKILL.md → morph-apply/references/media.md} +11 -74
  63. package/framework/skills/core/morph-apply/references/review.md +65 -0
  64. package/framework/skills/core/morph-plan/SKILL.md +42 -108
  65. package/framework/skills/core/morph-plan/references/critique.md +40 -0
  66. package/framework/skills/core/morph-plan/references/interview.md +25 -0
  67. package/framework/skills/core/morph-uiux/SKILL.md +47 -64
  68. package/framework/skills/core/morph-uiux/surfaces.json +32 -0
  69. package/framework/standards/STANDARDS.json +32 -5
  70. package/framework/standards/STANDARDS.meta.json +5 -1
  71. package/framework/standards/ai-agents/agent-session.md +2 -3
  72. package/framework/standards/ai-agents/context-providers.md +2 -2
  73. package/framework/standards/ai-agents/durable-workflows-hitl.md +2 -2
  74. package/framework/standards/ai-agents/providers/model-registry.md +2 -2
  75. package/framework/standards/ai-agents/rag-custom-pgvector.md +6 -6
  76. package/framework/standards/ai-agents/setup.md +1 -1
  77. package/framework/standards/ai-agents/tool-adapters.md +2 -2
  78. package/framework/standards/architecture/stack-baseline.md +47 -0
  79. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +2 -4
  80. package/framework/standards/frontend/design-system/ai-image-generation.md +51 -12
  81. package/framework/standards/frontend/design-system/ai-video-generation.md +50 -4
  82. package/framework/standards/frontend/design-system/art-direction.md +2 -2
  83. package/framework/standards/frontend/scroll-driven/frame-scrub.md +12 -2
  84. package/framework/standards/frontend/scroll-driven/scroll-components.md +76 -4
  85. package/framework/templates/.idea/morph-templates.xml +92 -0
  86. package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
  87. package/framework/templates/IDE-SNIPPETS.md +262 -262
  88. package/framework/templates/REGISTRY.json +1 -2
  89. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  90. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
  91. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
  92. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
  93. package/framework/templates/context/ARCHITECTURE.md +1 -1
  94. package/framework/templates/docs/plan.md +12 -12
  95. package/framework/templates/docs/ui-mockups.md +17 -105
  96. package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
  97. package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
  98. package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
  99. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  100. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  101. package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
  102. package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
  103. package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
  104. package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
  105. package/framework/templates/state.template.json +17 -17
  106. package/framework/templates/ui/design-system.css +226 -226
  107. package/package.json +1 -1
  108. package/src/commands/e2e/e2e.js +88 -23
  109. package/src/commands/graph/diff.js +74 -0
  110. package/src/commands/graph/status.js +1 -1
  111. package/src/commands/observability/cost.js +2 -4
  112. package/src/commands/observability/telemetry.js +1 -1
  113. package/src/commands/project/doctor.js +23 -39
  114. package/src/commands/project/fleet.js +5 -6
  115. package/src/commands/project/init.js +63 -36
  116. package/src/commands/project/stack-scan.js +3 -42
  117. package/src/commands/project/stack-set.js +26 -0
  118. package/src/commands/project/status.js +12 -13
  119. package/src/commands/project/update.js +39 -3
  120. package/src/commands/project/worktree.js +27 -16
  121. package/src/commands/state/advance.js +17 -17
  122. package/src/commands/state/approve.js +0 -6
  123. package/src/commands/state/archive.js +27 -1
  124. package/src/commands/state/auto-approval.js +1 -1
  125. package/src/commands/state/create.js +0 -5
  126. package/src/commands/state/finish.js +43 -1
  127. package/src/commands/state/gate-check.js +37 -30
  128. package/src/commands/state/gate-decision.js +3 -2
  129. package/src/commands/state/next.js +1 -0
  130. package/src/commands/state/recap.js +67 -0
  131. package/src/commands/state/report-check.js +39 -146
  132. package/src/commands/validation/plan-check.js +16 -11
  133. package/src/commands/validation/validate-feature.js +3 -3
  134. package/src/commands/validation/verify.js +6 -6
  135. package/src/core/paths/output-schema.js +3 -3
  136. package/src/core/state/state-manager.js +2 -4
  137. package/src/dashboard/app/components/CommandPalette.jsx +2 -5
  138. package/src/dashboard/app/components/GatePauses.jsx +116 -0
  139. package/src/dashboard/app/components/SessionMap.jsx +77 -0
  140. package/src/dashboard/app/main.jsx +13 -13
  141. package/src/dashboard/app/pages/Activity.jsx +4 -0
  142. package/src/dashboard/app/pages/AgentMap.jsx +1 -2
  143. package/src/dashboard/app/pages/FeatureDetail.jsx +129 -186
  144. package/src/dashboard/app/pages/Features.jsx +7 -7
  145. package/src/dashboard/app/pages/PhasePipeline.jsx +1 -1
  146. package/src/dashboard/app/pages/Portfolio.jsx +40 -5
  147. package/src/dashboard/scanner/activity-scanner.js +29 -0
  148. package/src/dashboard/scanner/agents-scanner.js +11 -14
  149. package/src/dashboard/scanner/features-scanner.js +45 -24
  150. package/src/dashboard/scanner/project-api.js +11 -2
  151. package/src/dashboard/scanner/skills-scanner.js +11 -1
  152. package/src/dashboard/vite.config.js +24 -24
  153. package/src/lib/e2e/applicability.js +3 -1
  154. package/src/lib/git/tree-state.js +1 -16
  155. package/src/lib/graph/diff-tree.js +127 -0
  156. package/src/lib/graph/graphify-runtime.js +12 -5
  157. package/src/lib/heavy/gate.js +22 -1
  158. package/src/lib/installers/memory-installer.js +2 -2
  159. package/src/lib/installers/rules-installer.js +57 -0
  160. package/src/lib/installers/stack-assets.js +17 -0
  161. package/src/lib/installers/stack-sync.js +219 -0
  162. package/src/lib/plan/checks.js +55 -110
  163. package/src/lib/plan/critique.js +28 -0
  164. package/src/lib/plan/media.js +42 -0
  165. package/src/lib/plan/plan-html.js +125 -0
  166. package/src/lib/plan/plan-parser.js +34 -45
  167. package/src/lib/recap/piper.js +36 -0
  168. package/src/lib/recap/recap.js +232 -0
  169. package/src/lib/review-reports.js +33 -7
  170. package/src/lib/risk-detector.js +90 -11
  171. package/src/lib/specs/screen-checklist.js +33 -48
  172. package/src/lib/stack/dotnet-build-ignores.js +8 -9
  173. package/src/lib/tasks/test-nodes.js +24 -6
  174. package/src/lib/tasks/test-runner.js +40 -1
  175. package/src/lib/telemetry/metrics.js +27 -29
  176. package/src/lib/validators/reuse/reuse-validator.js +1 -9
  177. package/src/lib/validators/verify-runner.js +50 -19
  178. package/src/lib/worktree/fleet-scanner.js +7 -20
  179. package/src/lib/worktree/worktree-audit.js +0 -37
  180. package/src/scripts/setup-infra.js +15 -50
  181. package/src/utils/agents-installer.js +27 -201
  182. package/src/utils/hooks-installer.js +11 -95
  183. package/framework/hooks/claude-code/core/warn-bash-source-write.js +0 -23
  184. package/framework/hooks/claude-code/statusline.py +0 -699
  185. package/framework/hooks/claude-code/statusline.sh +0 -11
  186. package/framework/hooks/shared/agent-reap.js +0 -74
  187. package/framework/hooks/shared/slice-progress.js +0 -110
  188. package/framework/skills/core/morph-hotfix/SKILL.md +0 -133
  189. package/framework/skills/core/morph-machine/SKILL.md +0 -46
  190. package/framework/skills/core/morph-review/SKILL.md +0 -129
  191. package/framework/skills/core/morph-standards/SKILL.md +0 -52
  192. package/framework/standards/PROVENANCE.json +0 -119
  193. package/src/commands/project/worktree-reap.js +0 -34
  194. package/src/commands/state/handoff.js +0 -65
  195. package/src/commands/validation/mutate.js +0 -263
  196. package/src/commands/validation/scout-check.js +0 -28
  197. package/src/lib/generators/handoff-generator.js +0 -172
  198. package/src/lib/mutation/adapters.js +0 -79
  199. package/src/lib/mutation/commands.js +0 -61
  200. package/src/lib/mutation/dotnet-introspection.js +0 -281
  201. package/src/lib/mutation/manifest.js +0 -144
  202. package/src/lib/mutation/plan.js +0 -44
  203. package/src/lib/mutation/report.js +0 -68
  204. package/src/lib/mutation/runner.js +0 -301
  205. package/src/lib/mutation/schemata.js +0 -60
  206. package/src/lib/mutation/snapshot.js +0 -65
  207. package/src/lib/mutation/subset.js +0 -109
  208. package/src/lib/mutation/trx.js +0 -50
  209. package/src/lib/scout/scout-check.js +0 -293
  210. package/src/lib/validators/traceability-check.js +0 -103
  211. package/src/lib/worktree/agent-reaper.js +0 -247
@@ -1,11 +1,10 @@
1
1
  import { join, dirname } from 'path';
2
2
  import { readFile } from 'fs/promises';
3
- import { existsSync, chmodSync, readdirSync } from 'fs';
3
+ import { existsSync, readdirSync } from 'fs';
4
4
  import { homedir } from 'os';
5
- import { execSync } from 'child_process';
6
5
  import { realEffects } from '../lib/installers/effects.js';
7
6
 
8
- const HOOKS_VERSION = '3.14.0';
7
+ const HOOKS_VERSION = '3.17.0';
9
8
 
10
9
  const OLD_DISPATCH_COMMAND = 'node framework/hooks/agent-teams/dispatch.js';
11
10
 
@@ -25,9 +24,6 @@ const MORPH_ALLOW = [
25
24
  'Edit(.morph/context/**)',
26
25
  'Bash(mkdir:.morph/**)',
27
26
  'Bash(ls:.morph/**)',
28
- // An auto-mode deny here pauses the review mutation round.
29
- 'Bash(morph-spec mutate:*)',
30
- 'Bash(npx morph-spec mutate:*)',
31
27
  ];
32
28
 
33
29
  const MORPH_PERMISSIONS = MORPH_DENY;
@@ -64,7 +60,7 @@ const MORPH_HOOKS = [
64
60
  hooks: [{
65
61
  type: 'command',
66
62
  command: 'node framework/hooks/claude-code/core/chain.js',
67
- args: ['pre-bash-denylist', 'test-budget', 'conventional-commit', 'block-destructive-worktree-removal', 'block-raw-worktree-add', 'warn-bash-source-write', 'heavy-gate', 'worktree-env-inject']
63
+ args: ['pre-bash-denylist', 'test-budget', 'conventional-commit', 'block-destructive-worktree-removal', 'block-raw-worktree-add', 'heavy-gate', 'worktree-env-inject']
68
64
  }]
69
65
  },
70
66
 
@@ -117,7 +113,7 @@ const MORPH_HOOKS = [
117
113
  hooks: [{
118
114
  type: 'command',
119
115
  command: 'node framework/hooks/claude-code/core/chain.js',
120
- args: ['telemetry-log', 'loop-detect', 'graph-refresh-kick', 'heavy-release', 'test-budget'],
116
+ args: ['telemetry-log', 'loop-detect', 'graph-refresh-kick', 'heavy-release', 'masked-exit'],
121
117
  timeout: 10
122
118
  }]
123
119
  },
@@ -129,7 +125,7 @@ const MORPH_HOOKS = [
129
125
  hooks: [{
130
126
  type: 'command',
131
127
  command: 'node framework/hooks/claude-code/core/chain.js',
132
- args: ['telemetry-log', 'heavy-release', 'test-budget'],
128
+ args: ['telemetry-log', 'heavy-release'],
133
129
  timeout: 5,
134
130
  async: true
135
131
  }]
@@ -254,6 +250,8 @@ export async function installClaudeHooks(targetPath, { fx = realEffects() } = {}
254
250
  const STALE_ALLOW = [
255
251
  'Write(.morph/features/**)',
256
252
  'Write(.morph/context/**)',
253
+ 'Bash(morph-spec mutate:*)',
254
+ 'Bash(npx morph-spec mutate:*)',
257
255
  ];
258
256
  settings.permissions.allow = settings.permissions.allow.filter(
259
257
  p => !MORPH_ALLOW.includes(p) && !STALE_ALLOW.includes(p)
@@ -292,78 +290,6 @@ export async function installClaudeHooks(targetPath, { fx = realEffects() } = {}
292
290
  return { installed, updated: !alreadyCurrent };
293
291
  }
294
292
 
295
- function findPython() {
296
- if (process.platform !== 'win32') {
297
- for (const cmd of ['python3', 'python']) {
298
- try {
299
- const ver = execSync(`${cmd} --version`, { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] });
300
- if ((ver + '').includes('Python 3')) return cmd;
301
- } catch { /* not on PATH */ }
302
- }
303
- return null;
304
- }
305
- for (const cmd of ['python3', 'py', 'python']) {
306
- try {
307
- const ver = execSync(`${cmd} --version`, { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] });
308
- if ((ver + '').includes('Python 3')) return cmd;
309
- } catch { /* not on PATH */ }
310
- }
311
- const base = join(homedir(), 'AppData', 'Local', 'Programs', 'Python');
312
- if (existsSync(base)) {
313
- let dirs;
314
- try { dirs = readdirSync(base); } catch { dirs = []; }
315
- const py3 = dirs
316
- .filter(d => /^Python3\d*/i.test(d))
317
- .sort()
318
- .reverse();
319
- for (const dir of py3) {
320
- const exe = join(base, dir, 'python.exe');
321
- if (existsSync(exe)) return exe;
322
- }
323
- }
324
- return null;
325
- }
326
-
327
- function tryInstallPython() {
328
- const log = (msg) => process.stdout.write(` ${msg}\n`);
329
- log('⚠ Python 3 not found — attempting automatic installation...');
330
-
331
- try {
332
- if (process.platform === 'win32') {
333
- execSync('winget install -e --id Python.Python.3.12 --accept-source-agreements --accept-package-agreements', {
334
- stdio: 'inherit',
335
- timeout: 120_000,
336
- });
337
- } else if (process.platform === 'darwin') {
338
- execSync('brew install python3', { stdio: 'inherit', timeout: 120_000 });
339
- } else {
340
- try {
341
- execSync('sudo apt-get update -qq && sudo apt-get install -y python3', { stdio: 'inherit', timeout: 120_000 });
342
- } catch {
343
- execSync('sudo dnf install -y python3', { stdio: 'inherit', timeout: 120_000 });
344
- }
345
- }
346
- log('✓ Python 3 installed successfully.');
347
- return true;
348
- } catch (err) {
349
- log(`✗ Automatic Python installation failed: ${err.message}`);
350
- log(' Please install Python 3 manually: https://www.python.org/downloads/');
351
- return false;
352
- }
353
- }
354
-
355
- function resolvePythonForStatusline() {
356
- let python = findPython();
357
- if (python) return python;
358
-
359
- if (tryInstallPython()) {
360
- python = findPython();
361
- if (python) return python;
362
- }
363
-
364
- return 'python3';
365
- }
366
-
367
293
  /**
368
294
  * Writes OUTSIDE the project (`~/.claude/`), so `--dry-run` must name these effects separately.
369
295
  * @returns {Promise<{ installed: boolean, globalDir: string }>}
@@ -372,23 +298,13 @@ export async function installGlobalStatusline(hooksSourceDir, globalClaudeDirOve
372
298
  const globalDir = globalClaudeDirOverride || join(homedir(), '.claude');
373
299
  fx.ensureDir(globalDir);
374
300
 
375
- const scripts = ['statusline.sh', 'statusline.py'];
376
- for (const fname of scripts) {
377
- const src = join(hooksSourceDir, fname);
378
- if (existsSync(src)) {
379
- fx.copyFile(src, join(globalDir, fname));
380
- if (process.platform !== 'win32' && !fx.dryRun) {
381
- try { chmodSync(join(globalDir, fname), 0o755); } catch { /* non-critical */ }
382
- }
383
- }
301
+ fx.copyFile(join(hooksSourceDir, '..', 'statusline.js'), join(globalDir, 'statusline.js'));
302
+ for (const legacy of ['statusline.py', 'statusline.sh']) {
303
+ if (existsSync(join(globalDir, legacy))) fx.remove(join(globalDir, legacy));
384
304
  }
385
305
 
386
306
  const settingsPath = join(globalDir, 'settings.json');
387
-
388
- // Claude Code on Windows cannot execute .sh directly.
389
- const statuslineCommand = process.platform === 'win32'
390
- ? `"${resolvePythonForStatusline()}" "${join(globalDir, 'statusline.py').replace(/\\/g, '/')}"`
391
- : join(globalDir, 'statusline.sh').replace(/\\/g, '/');
307
+ const statuslineCommand = `node "${join(globalDir, 'statusline.js').replace(/\\/g, '/')}"`;
392
308
 
393
309
  // Without refreshInterval the status line only re-renders on events, freezing
394
310
  // the rate-limit countdown through a long turn. Shallow merge: only `statusLine` is ours.
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env node
2
- // Warn only: a source file written by the shell skips every Write/Edit guard. The command still runs.
3
- import { contextResult, runStandalone } from '../../shared/hook-response.js';
4
- import { stateExists } from '../../shared/state-reader.js';
5
- import { writeTargets } from '../../shared/command-tokens.js';
6
- import { isProjectSource } from '../../shared/source-files.js';
7
-
8
- export async function run(payload) {
9
- try {
10
- if (!stateExists()) return null;
11
- const sources = writeTargets(payload?.tool_input?.command || '').filter(isProjectSource);
12
- if (!sources.length) return null;
13
- return contextResult(
14
- `⚠️ Código do projeto escrito pelo Bash (${sources.join(', ')}): os guards de escrita (fase, arquivo protegido, comment-guard) ` +
15
- 'só enxergam Write/Edit. Reescreva esse arquivo por Write/Edit.',
16
- 'PreToolUse',
17
- );
18
- } catch {
19
- return null;
20
- }
21
- }
22
-
23
- await runStandalone(run);