@polymorphism-tech/morph-spec 4.10.6 → 4.10.8

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 (149) hide show
  1. package/CLAUDE.md +3 -0
  2. package/LICENSE +71 -71
  3. package/README.md +379 -379
  4. package/bin/morph-spec.js +89 -0
  5. package/bin/task-manager.js +59 -6
  6. package/claude-plugin.json +14 -14
  7. package/docs/CHEATSHEET.md +1 -1
  8. package/docs/QUICKSTART.md +206 -206
  9. package/framework/agents/README.md +14 -14
  10. package/framework/agents/architecture/standards-architect.md +159 -159
  11. package/framework/agents/frontend/blazor-builder.md +13 -0
  12. package/framework/agents/frontend/css-specialist.md +87 -0
  13. package/framework/agents/frontend/nextjs-expert.md +13 -0
  14. package/framework/agents/frontend/nextjs-ui-specialist.md +218 -0
  15. package/framework/agents/frontend/ui-ux-designer.md +80 -10
  16. package/framework/agents/infrastructure/azure-architect.md +149 -149
  17. package/framework/agents/infrastructure/infra-architect.md +48 -48
  18. package/framework/agents.json +2268 -2567
  19. package/framework/hooks/README.md +204 -204
  20. package/framework/hooks/claude-code/post-tool-use/dispatch.js +10 -5
  21. package/framework/hooks/claude-code/session-start/inject-morph-context.js +10 -24
  22. package/framework/hooks/shared/phase-utils.js +139 -139
  23. package/framework/hooks/shared/worktree-helpers.js +30 -8
  24. package/framework/rules/csharp-standards.md +13 -13
  25. package/framework/rules/frontend-standards.md +13 -13
  26. package/framework/rules/infrastructure-standards.md +16 -16
  27. package/framework/rules/testing-standards.md +14 -14
  28. package/framework/skills/README.md +0 -1
  29. package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +12 -0
  30. package/framework/skills/level-0-meta/morph-code-review-nextjs/references/review-example-nextjs.md +254 -254
  31. package/framework/skills/level-0-meta/morph-init/SKILL.md +88 -3
  32. package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +247 -247
  33. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +270 -270
  34. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +515 -499
  35. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +508 -471
  36. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +12 -1
  37. package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +272 -258
  38. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +317 -311
  39. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +424 -323
  40. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  41. package/framework/standards/STANDARDS.json +2040 -2040
  42. package/framework/standards/frontend/nextjs/motion-patterns.md +321 -0
  43. package/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -17
  44. package/framework/templates/README.md +814 -814
  45. package/framework/templates/code/dotnet/contracts/Commands.cs +74 -74
  46. package/framework/templates/code/dotnet/contracts/Entities.cs +25 -25
  47. package/framework/templates/code/dotnet/contracts/Queries.cs +74 -74
  48. package/framework/templates/code/dotnet/contracts/README.md +74 -74
  49. package/framework/templates/code/dotnet/contracts/api-contracts.cs +173 -173
  50. package/framework/templates/code/dotnet/frontend/component.razor +239 -239
  51. package/framework/templates/code/dotnet/jobs/agent.cs +163 -163
  52. package/framework/templates/code/dotnet/jobs/job.cs +171 -171
  53. package/framework/templates/code/dotnet/test.cs +239 -239
  54. package/framework/templates/code/sql/rls-policy.sql +57 -57
  55. package/framework/templates/code/sql/supabase-migration.sql +100 -100
  56. package/framework/templates/code/sql/supabase-migration.template.sql +113 -113
  57. package/framework/templates/code/typescript/contracts.ts +168 -168
  58. package/framework/templates/context/CONTEXT.md +181 -181
  59. package/framework/templates/context/design-system.md +211 -0
  60. package/framework/templates/docs/proposal.md +182 -182
  61. package/framework/templates/docs/user-stories.md +34 -34
  62. package/framework/templates/examples/design-system-examples.md +357 -357
  63. package/framework/templates/examples/spec-examples.md +90 -90
  64. package/framework/templates/feature/decisions.md +187 -187
  65. package/framework/templates/feature/recap.md +146 -146
  66. package/framework/templates/feature/tasks.md +199 -199
  67. package/framework/templates/infrastructure/azure/README.md +286 -286
  68. package/framework/templates/infrastructure/azure/deploy-checklist.md +426 -426
  69. package/framework/templates/infrastructure/azure/parameters.dev.json +29 -29
  70. package/framework/templates/infrastructure/azure/parameters.prod.json +29 -29
  71. package/framework/templates/infrastructure/azure/parameters.staging.json +29 -29
  72. package/framework/templates/infrastructure/docker/docker-compose.template.yml +67 -67
  73. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  74. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  75. package/framework/templates/infrastructure/docker/easypanel.template.json +54 -54
  76. package/package.json +82 -82
  77. package/src/commands/agents/agent-metrics.js +174 -0
  78. package/src/commands/agents/audit-dispatch.js +82 -0
  79. package/src/commands/agents/detect-agents.js +275 -0
  80. package/src/commands/agents/dispatch-agents.js +41 -135
  81. package/src/commands/agents/index.js +13 -4
  82. package/src/commands/agents/manage-agents.js +352 -0
  83. package/src/commands/project/doctor.js +59 -0
  84. package/src/commands/project/install-plugin-cmd.js +28 -28
  85. package/src/commands/project/setup-infra-cmd.js +12 -12
  86. package/src/commands/project/update.js +1 -17
  87. package/src/commands/project/worktree.js +58 -2
  88. package/src/commands/state/advance-phase.js +11 -3
  89. package/src/commands/tasks/index.js +4 -4
  90. package/src/commands/templates/index.js +5 -5
  91. package/src/commands/utils/index.js +3 -3
  92. package/src/commands/validation/index.js +4 -4
  93. package/src/core/state/phase-state-machine.js +217 -217
  94. package/src/core/state/state-manager.js +81 -0
  95. package/src/lib/agents/agents-manager.js +349 -0
  96. package/src/lib/agents/metrics-calculator.js +125 -0
  97. package/src/lib/agents/output-collector.js +75 -0
  98. package/src/lib/generators/context-generator.js +8 -7
  99. package/src/lib/generators/design-system-generator.js +298 -298
  100. package/src/lib/generators/index.js +10 -10
  101. package/src/lib/generators/metadata-extractor.js +387 -387
  102. package/src/lib/stack-filter.js +65 -65
  103. package/src/lib/standards/index.js +7 -7
  104. package/src/lib/standards/standards-context-injector.js +302 -302
  105. package/src/lib/tasks/task-parser.js +94 -3
  106. package/src/lib/validators/architecture/architecture-validator.js +387 -387
  107. package/src/lib/validators/architecture/index.js +7 -7
  108. package/src/lib/validators/blazor/blazor-concurrency-analyzer.js +316 -316
  109. package/src/lib/validators/blazor/blazor-state-validator.js +279 -279
  110. package/src/lib/validators/blazor/blazor-validator.js +369 -369
  111. package/src/lib/validators/blazor/index.js +9 -9
  112. package/src/lib/validators/checkpoint-persistence.js +39 -0
  113. package/src/lib/validators/content/content-validator.js +287 -279
  114. package/src/lib/validators/content/index.js +7 -7
  115. package/src/lib/validators/contracts/index.js +7 -7
  116. package/src/lib/validators/css/css-validator.js +352 -352
  117. package/src/lib/validators/css/index.js +7 -7
  118. package/src/lib/validators/design-system/design-system-validator.js +231 -231
  119. package/src/lib/validators/design-system/index.js +7 -7
  120. package/src/lib/validators/nextjs/index.js +6 -6
  121. package/src/lib/validators/nextjs/next-component-validator.js +183 -183
  122. package/src/lib/validators/packages/index.js +7 -7
  123. package/src/lib/validators/packages/package-validator.js +360 -360
  124. package/src/lib/validators/shared/index.js +12 -12
  125. package/src/lib/validators/shared/issue-counter.js +18 -18
  126. package/src/lib/validators/shared/result-formatter.js +124 -124
  127. package/src/lib/validators/spec-validator.js +2 -2
  128. package/src/lib/validators/ui/index.js +7 -7
  129. package/src/lib/validators/ui/ui-contrast-validator.js +422 -422
  130. package/src/lib/validators/validation-runner.js +20 -0
  131. package/src/scripts/global-install.js +58 -58
  132. package/src/scripts/install-plugin.js +126 -126
  133. package/src/scripts/setup-infra.js +1 -17
  134. package/src/utils/agent-id-mapper.js +11 -0
  135. package/src/utils/agents-installer.js +40 -8
  136. package/src/utils/claude-md-injector.js +90 -90
  137. package/src/utils/claude-settings-manager.js +1 -1
  138. package/src/utils/file-copier.js +200 -196
  139. package/src/utils/hooks-installer.js +556 -739
  140. package/src/utils/logger.js +32 -32
  141. package/src/utils/skills-installer.js +178 -178
  142. package/src/utils/tier-helpers.js +24 -0
  143. package/src/utils/version-checker.js +175 -175
  144. package/framework/agents/architecture/po-pm-advisor.md +0 -203
  145. package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +0 -68
  146. package/framework/skills/level-1-workflows/morph-phase-implement/.morph/logs/activity.json +0 -38
  147. package/framework/skills/level-1-workflows/morph-phase-tasks/.morph/logs/activity.json +0 -14
  148. package/framework/templates/.idea/morph-templates.xml +0 -92
  149. package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
@@ -1,175 +1,175 @@
1
- import { readFileSync } from 'fs';
2
- import { join, dirname } from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { pathExists, readJson, writeJson } from './file-copier.js';
5
-
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
7
-
8
- /**
9
- * Get the current CLI version from package.json
10
- * @returns {string} Version string (e.g., "1.0.4")
11
- */
12
- export function getInstalledCLIVersion() {
13
- try {
14
- const pkgPath = join(__dirname, '..', '..', 'package.json');
15
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
16
- return pkg.version;
17
- } catch (error) {
18
- return 'unknown';
19
- }
20
- }
21
-
22
- /**
23
- * Get the latest version from npm registry
24
- * @param {string} packageName - The package name (default: @polymorphism-tech/morph-spec)
25
- * @returns {Promise<string|null>} Latest version or null if failed
26
- */
27
- export async function getLatestNPMVersion(packageName = '@polymorphism-tech/morph-spec') {
28
- try {
29
- const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
30
- if (!response.ok) return null;
31
- const data = await response.json();
32
- return data.version;
33
- } catch (error) {
34
- return null;
35
- }
36
- }
37
-
38
- /**
39
- * Get the MORPH version installed in the project
40
- * @param {string} projectPath - Path to the project
41
- * @returns {Promise<object|null>} Version info object or null if not found
42
- */
43
- export async function getProjectMorphVersion(projectPath) {
44
- try {
45
- const versionPath = join(projectPath, '.morph', '.morphversion');
46
- if (!(await pathExists(versionPath))) {
47
- return null;
48
- }
49
- return await readJson(versionPath);
50
- } catch (error) {
51
- return null;
52
- }
53
- }
54
-
55
- /**
56
- * Save the MORPH version to the project
57
- * @param {string} projectPath - Path to the project
58
- * @param {string} version - Version to save
59
- * @returns {Promise<void>}
60
- */
61
- export async function saveProjectMorphVersion(projectPath, version) {
62
- const versionPath = join(projectPath, '.morph', '.morphversion');
63
- const versionInfo = {
64
- morphVersion: version,
65
- installedAt: new Date().toISOString(),
66
- cliVersion: version
67
- };
68
- await writeJson(versionPath, versionInfo);
69
- }
70
-
71
- /**
72
- * Compare two semver versions
73
- * @param {string} v1 - First version
74
- * @param {string} v2 - Second version
75
- * @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
76
- */
77
- export function compareVersions(v1, v2) {
78
- if (!v1 || !v2) return 0;
79
-
80
- const parts1 = v1.split('.').map(Number);
81
- const parts2 = v2.split('.').map(Number);
82
-
83
- for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
84
- const num1 = parts1[i] || 0;
85
- const num2 = parts2[i] || 0;
86
-
87
- if (num1 < num2) return -1;
88
- if (num1 > num2) return 1;
89
- }
90
-
91
- return 0;
92
- }
93
-
94
- /**
95
- * Detect how the CLI was installed
96
- * @returns {'global'|'npx'|'unknown'}
97
- */
98
- export function detectInstallMethod() {
99
- // Check if running via npx
100
- if (process.env.npm_execpath && process.env.npm_execpath.includes('npx')) {
101
- return 'npx';
102
- }
103
-
104
- // Check if installed globally
105
- const isGlobal = process.env.npm_config_global === 'true' ||
106
- process.execPath.includes('node_modules');
107
-
108
- if (isGlobal) {
109
- return 'global';
110
- }
111
-
112
- return 'unknown';
113
- }
114
-
115
- /**
116
- * Get update instructions based on install method
117
- * @param {string} method - Install method ('global', 'npx', 'unknown')
118
- * @returns {string[]} Array of instruction strings
119
- */
120
- export function getUpdateInstructions(method) {
121
- switch (method) {
122
- case 'global':
123
- return [
124
- 'npm install -g @polymorphism-tech/morph-spec@latest',
125
- 'morph-spec update'
126
- ];
127
- case 'npx':
128
- return [
129
- 'npx @polymorphism-tech/morph-spec@latest update'
130
- ];
131
- default:
132
- return [
133
- 'npm install -g @polymorphism-tech/morph-spec@latest',
134
- 'morph-spec update',
135
- '',
136
- 'Or use npx:',
137
- 'npx @polymorphism-tech/morph-spec@latest update'
138
- ];
139
- }
140
- }
141
-
142
- /**
143
- * Check if CLI version is outdated
144
- * @returns {Promise<{isOutdated: boolean, current: string, latest: string|null}>}
145
- */
146
- export async function checkCLIOutdated() {
147
- const current = getInstalledCLIVersion();
148
- const latest = await getLatestNPMVersion();
149
-
150
- if (!latest) {
151
- return { isOutdated: false, current, latest: null };
152
- }
153
-
154
- const isOutdated = compareVersions(current, latest) < 0;
155
-
156
- return { isOutdated, current, latest };
157
- }
158
-
159
- /**
160
- * Check if project MORPH version is outdated
161
- * @param {string} projectPath - Path to the project
162
- * @returns {Promise<{isOutdated: boolean, current: string|null, cliVersion: string}>}
163
- */
164
- export async function checkProjectOutdated(projectPath) {
165
- const cliVersion = getInstalledCLIVersion();
166
- const projectVersion = await getProjectMorphVersion(projectPath);
167
-
168
- if (!projectVersion) {
169
- return { isOutdated: false, current: null, cliVersion };
170
- }
171
-
172
- const isOutdated = compareVersions(projectVersion.morphVersion, cliVersion) < 0;
173
-
174
- return { isOutdated, current: projectVersion.morphVersion, cliVersion };
175
- }
1
+ import { readFileSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { pathExists, readJson, writeJson } from './file-copier.js';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ /**
9
+ * Get the current CLI version from package.json
10
+ * @returns {string} Version string (e.g., "1.0.4")
11
+ */
12
+ export function getInstalledCLIVersion() {
13
+ try {
14
+ const pkgPath = join(__dirname, '..', '..', 'package.json');
15
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
16
+ return pkg.version;
17
+ } catch (error) {
18
+ return 'unknown';
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Get the latest version from npm registry
24
+ * @param {string} packageName - The package name (default: @polymorphism-tech/morph-spec)
25
+ * @returns {Promise<string|null>} Latest version or null if failed
26
+ */
27
+ export async function getLatestNPMVersion(packageName = '@polymorphism-tech/morph-spec') {
28
+ try {
29
+ const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`);
30
+ if (!response.ok) return null;
31
+ const data = await response.json();
32
+ return data.version;
33
+ } catch (error) {
34
+ return null;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Get the MORPH version installed in the project
40
+ * @param {string} projectPath - Path to the project
41
+ * @returns {Promise<object|null>} Version info object or null if not found
42
+ */
43
+ export async function getProjectMorphVersion(projectPath) {
44
+ try {
45
+ const versionPath = join(projectPath, '.morph', '.morphversion');
46
+ if (!(await pathExists(versionPath))) {
47
+ return null;
48
+ }
49
+ return await readJson(versionPath);
50
+ } catch (error) {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Save the MORPH version to the project
57
+ * @param {string} projectPath - Path to the project
58
+ * @param {string} version - Version to save
59
+ * @returns {Promise<void>}
60
+ */
61
+ export async function saveProjectMorphVersion(projectPath, version) {
62
+ const versionPath = join(projectPath, '.morph', '.morphversion');
63
+ const versionInfo = {
64
+ morphVersion: version,
65
+ installedAt: new Date().toISOString(),
66
+ cliVersion: version
67
+ };
68
+ await writeJson(versionPath, versionInfo);
69
+ }
70
+
71
+ /**
72
+ * Compare two semver versions
73
+ * @param {string} v1 - First version
74
+ * @param {string} v2 - Second version
75
+ * @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
76
+ */
77
+ export function compareVersions(v1, v2) {
78
+ if (!v1 || !v2) return 0;
79
+
80
+ const parts1 = v1.split('.').map(Number);
81
+ const parts2 = v2.split('.').map(Number);
82
+
83
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
84
+ const num1 = parts1[i] || 0;
85
+ const num2 = parts2[i] || 0;
86
+
87
+ if (num1 < num2) return -1;
88
+ if (num1 > num2) return 1;
89
+ }
90
+
91
+ return 0;
92
+ }
93
+
94
+ /**
95
+ * Detect how the CLI was installed
96
+ * @returns {'global'|'npx'|'unknown'}
97
+ */
98
+ export function detectInstallMethod() {
99
+ // Check if running via npx
100
+ if (process.env.npm_execpath && process.env.npm_execpath.includes('npx')) {
101
+ return 'npx';
102
+ }
103
+
104
+ // Check if installed globally
105
+ const isGlobal = process.env.npm_config_global === 'true' ||
106
+ process.execPath.includes('node_modules');
107
+
108
+ if (isGlobal) {
109
+ return 'global';
110
+ }
111
+
112
+ return 'unknown';
113
+ }
114
+
115
+ /**
116
+ * Get update instructions based on install method
117
+ * @param {string} method - Install method ('global', 'npx', 'unknown')
118
+ * @returns {string[]} Array of instruction strings
119
+ */
120
+ export function getUpdateInstructions(method) {
121
+ switch (method) {
122
+ case 'global':
123
+ return [
124
+ 'npm install -g @polymorphism-tech/morph-spec@latest',
125
+ 'morph-spec update'
126
+ ];
127
+ case 'npx':
128
+ return [
129
+ 'npx @polymorphism-tech/morph-spec@latest update'
130
+ ];
131
+ default:
132
+ return [
133
+ 'npm install -g @polymorphism-tech/morph-spec@latest',
134
+ 'morph-spec update',
135
+ '',
136
+ 'Or use npx:',
137
+ 'npx @polymorphism-tech/morph-spec@latest update'
138
+ ];
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Check if CLI version is outdated
144
+ * @returns {Promise<{isOutdated: boolean, current: string, latest: string|null}>}
145
+ */
146
+ export async function checkCLIOutdated() {
147
+ const current = getInstalledCLIVersion();
148
+ const latest = await getLatestNPMVersion();
149
+
150
+ if (!latest) {
151
+ return { isOutdated: false, current, latest: null };
152
+ }
153
+
154
+ const isOutdated = compareVersions(current, latest) < 0;
155
+
156
+ return { isOutdated, current, latest };
157
+ }
158
+
159
+ /**
160
+ * Check if project MORPH version is outdated
161
+ * @param {string} projectPath - Path to the project
162
+ * @returns {Promise<{isOutdated: boolean, current: string|null, cliVersion: string}>}
163
+ */
164
+ export async function checkProjectOutdated(projectPath) {
165
+ const cliVersion = getInstalledCLIVersion();
166
+ const projectVersion = await getProjectMorphVersion(projectPath);
167
+
168
+ if (!projectVersion) {
169
+ return { isOutdated: false, current: null, cliVersion };
170
+ }
171
+
172
+ const isOutdated = compareVersions(projectVersion.morphVersion, cliVersion) < 0;
173
+
174
+ return { isOutdated, current: projectVersion.morphVersion, cliVersion };
175
+ }
@@ -1,203 +0,0 @@
1
- ---
2
- name: po-pm-advisor
3
- description: PO/PM Advisor specialist for clarifying product requirements, defining acceptance criteria, writing user stories, and evaluating feature ROI. Use when defining feature scope, writing user stories with acceptance criteria, prioritizing the backlog, or resolving requirements conflicts.
4
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
- ---
6
-
7
- # PO/PM Advisor
8
-
9
- Especialista em requisitos, priorização e gestão de produto para clarificar features e ROI.
10
-
11
- ## Responsabilidades
12
-
13
- 1. **Clarificar requisitos** ambíguos ou incompletos
14
- 2. **Priorizar features** por valor de negócio
15
- 3. **Calcular ROI** e esforço estimado
16
- 4. **Definir critérios** de aceitação
17
-
18
- ## Triggers
19
-
20
- Keywords: `unclear`, `requirements`, `priority`, `ROI`, `mvp`, `scope`, `acceptance criteria`, `user story`
21
-
22
- ## Framework de Clarificação
23
-
24
- ### Perguntas Essenciais
25
-
26
- Quando receber uma feature request ambígua, faça estas perguntas:
27
-
28
- 1. **Quem?** - Qual o usuário/persona principal?
29
- 2. **O quê?** - O que exatamente deve acontecer?
30
- 3. **Por quê?** - Qual problema resolve? Qual o valor?
31
- 4. **Quando?** - Urgência? Deadline externo?
32
- 5. **Como medir?** - Como saberemos que funcionou?
33
-
34
- ### Template de User Story
35
-
36
- ```markdown
37
- ## User Story: {Nome da Feature}
38
-
39
- **Como** {persona/usuário},
40
- **Eu quero** {ação/funcionalidade},
41
- **Para que** {benefício/valor}.
42
-
43
- ### Critérios de Aceitação
44
-
45
- **Dado** {contexto inicial},
46
- **Quando** {ação do usuário},
47
- **Então** {resultado esperado}.
48
-
49
- ### Fora do Escopo
50
-
51
- - {Item explicitamente excluído}
52
-
53
- ### Perguntas Pendentes
54
-
55
- - [ ] {Dúvida não resolvida}
56
- ```
57
-
58
- ## Matriz de Priorização (RICE)
59
-
60
- | Fator | Descrição | Escala |
61
- |-------|-----------|--------|
62
- | **R**each | Quantos usuários impacta | 1-10 |
63
- | **I**mpact | Quanto impacta cada usuário | 0.25, 0.5, 1, 2, 3 |
64
- | **C**onfidence | Confiança nas estimativas | 0-100% |
65
- | **E**ffort | Pessoa-semanas de trabalho | 1+ |
66
-
67
- ```
68
- RICE Score = (Reach × Impact × Confidence) / Effort
69
- ```
70
-
71
- ### Exemplo
72
-
73
- | Feature | Reach | Impact | Confidence | Effort | Score |
74
- |---------|-------|--------|------------|--------|-------|
75
- | Login social | 8 | 1 | 80% | 1 | 6.4 |
76
- | Dashboard | 5 | 2 | 90% | 3 | 3.0 |
77
- | Export PDF | 3 | 0.5 | 100% | 0.5 | 3.0 |
78
- | Dark mode | 4 | 0.25 | 100% | 1 | 1.0 |
79
-
80
- ## MVP vs Nice-to-Have
81
-
82
- ### Critérios para MVP
83
-
84
- 1. **Resolve o problema core** do usuário
85
- 2. **Diferencia** da concorrência
86
- 3. **Validável** em 2-4 semanas
87
- 4. **Mensurável** (métricas definidas)
88
-
89
- ### Framework MoSCoW
90
-
91
- | Categoria | Significado | Exemplo |
92
- |-----------|-------------|---------|
93
- | **M**ust have | Essencial, sem isso não funciona | Login, CRUD básico |
94
- | **S**hould have | Importante, mas não crítico | Filtros avançados |
95
- | **C**ould have | Desejável se houver tempo | Exportar relatório |
96
- | **W**on't have | Fora deste release | Integração X |
97
-
98
- ## Estimativa de Esforço
99
-
100
- ### T-Shirt Sizing
101
-
102
- | Size | Dias | Complexidade |
103
- |------|------|--------------|
104
- | XS | 0.5 | Task trivial |
105
- | S | 1-2 | Feature simples |
106
- | M | 3-5 | Feature com complexidade |
107
- | L | 5-10 | Feature complexa |
108
- | XL | 10+ | Épico, precisa quebrar |
109
-
110
- ### Fatores de Risco
111
-
112
- Multiplicar estimativa por:
113
-
114
- | Fator | Multiplicador |
115
- |-------|---------------|
116
- | Tecnologia nova | 1.5x |
117
- | Integração externa | 1.3x |
118
- | Requisitos vagos | 1.5x |
119
- | Primeiro da equipe | 1.3x |
120
-
121
- ## Template de ADR (Architecture Decision Record)
122
-
123
- ```markdown
124
- # ADR-{XXX}: {Título da Decisão}
125
-
126
- ## Status
127
- {PROPOSED | ACCEPTED | DEPRECATED | SUPERSEDED}
128
-
129
- ## Contexto
130
- {Situação que requer decisão}
131
-
132
- ## Opções Consideradas
133
-
134
- ### Opção 1: {Nome}
135
- - Prós: ...
136
- - Contras: ...
137
- - Custo: ...
138
-
139
- ### Opção 2: {Nome}
140
- - Prós: ...
141
- - Contras: ...
142
- - Custo: ...
143
-
144
- ## Decisão
145
- {Opção escolhida e por quê}
146
-
147
- ## Consequências
148
- - {Implicação positiva}
149
- - {Implicação negativa}
150
- - {Trade-off aceito}
151
- ```
152
-
153
- ## Cálculo de ROI
154
-
155
- ```markdown
156
- ## ROI Estimado: {Feature}
157
-
158
- ### Benefícios (anual)
159
- - Aumento de conversão: R$ X
160
- - Redução de suporte: R$ Y
161
- - Economia de tempo: R$ Z
162
- - **Total Benefícios**: R$ (X+Y+Z)
163
-
164
- ### Custos
165
- - Desenvolvimento: R$ A (horas × rate)
166
- - Infraestrutura: R$ B/mês × 12
167
- - Manutenção: R$ C/ano
168
- - **Total Custos**: R$ (A+B+C)
169
-
170
- ### ROI
171
- **ROI = (Benefícios - Custos) / Custos × 100**
172
-
173
- ROI = (X+Y+Z - A+B+C) / (A+B+C) × 100 = **{N}%**
174
-
175
- ### Payback
176
- **Meses = Custo Inicial / (Benefício Mensal - Custo Mensal)**
177
- ```
178
-
179
- ## Red Flags em Requisitos
180
-
181
- Alertar quando detectar:
182
-
183
- - "Deve ser igual ao [concorrente X]" sem especificar
184
- - "Simples" ou "rápido" sem estimativa
185
- - "Usuários querem..." sem evidência
186
- - Escopo crescente sem priorização
187
- - Deadline impossível sem trade-offs
188
-
189
- ## Checklist de Requisitos
190
-
191
- - [ ] Persona/usuário definido
192
- - [ ] Problema claramente articulado
193
- - [ ] Valor de negócio quantificado
194
- - [ ] Critérios de aceitação escritos
195
- - [ ] Fora do escopo explícito
196
- - [ ] Dependências mapeadas
197
- - [ ] Riscos identificados
198
- - [ ] Estimativa de esforço
199
- - [ ] Prioridade definida (RICE/MoSCoW)
200
-
201
- ---
202
-
203
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,68 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * UserPromptSubmit Hook: Set Terminal Title
5
- *
6
- * Event: UserPromptSubmit
7
- *
8
- * Extracts a concise title from the user's prompt and sets it as the
9
- * terminal window title using ANSI escape sequences written to /dev/tty.
10
- * Also saves to ~/.claude/terminal_title for shell hook integration.
11
- *
12
- * Title format: "[first ~40 chars of prompt, truncated at word boundary]"
13
- *
14
- * Fail-open: exits 0 on any error.
15
- */
16
-
17
- import { readStdin } from '../../shared/stdin-reader.js';
18
- import { openSync, writeSync, closeSync } from 'fs';
19
- import { writeFile, mkdir } from 'fs/promises';
20
- import { homedir } from 'os';
21
- import { join } from 'path';
22
- import { logHookActivity } from '../../shared/activity-logger.js';
23
-
24
- try {
25
- const payload = await readStdin();
26
- if (!payload) process.exit(0);
27
-
28
- const prompt = payload?.prompt || payload?.user_prompt || payload?.content || '';
29
- if (!prompt || prompt.length < 3) process.exit(0);
30
-
31
- // Generate title: clean prompt, truncate at word boundary within 40 chars
32
- const cleaned = prompt.replace(/[\r\n\t]+/g, ' ').replace(/\s+/g, ' ').trim();
33
- const maxLen = 40;
34
- let title = cleaned.slice(0, maxLen);
35
- if (cleaned.length > maxLen) {
36
- const lastSpace = title.lastIndexOf(' ');
37
- if (lastSpace > 20) title = title.slice(0, lastSpace);
38
- }
39
-
40
- const prefix = process.env.CLAUDE_TITLE_PREFIX ? `${process.env.CLAUDE_TITLE_PREFIX} ` : '';
41
- const finalTitle = `${prefix}${title}`;
42
-
43
- // Save to session-specific file (MORPH_TERMINAL_TITLE_FILE) or fallback to global
44
- // MORPH_TERMINAL_TITLE_FILE is set by the shell wrapper (Invoke-Claude / claude())
45
- // per-session so multiple terminal windows don't interfere with each other.
46
- try {
47
- const titleFilePath = process.env.MORPH_TERMINAL_TITLE_FILE
48
- || join(homedir(), '.claude', 'terminal_title');
49
- const claudeDir = join(homedir(), '.claude');
50
- await mkdir(claudeDir, { recursive: true });
51
- await writeFile(titleFilePath, finalTitle, 'utf-8');
52
- } catch { /* non-critical */ }
53
-
54
- // Write ANSI escape to terminal device (bypasses stdout capture by Claude Code)
55
- // Windows uses \\.\CONOUT$ as the equivalent of /dev/tty
56
- let wrote = false;
57
- try {
58
- const devicePath = process.platform === 'win32' ? '\\\\.\\CONOUT$' : '/dev/tty';
59
- const tty = openSync(devicePath, 'w');
60
- writeSync(tty, `\x1b]0;${finalTitle}\x07`);
61
- closeSync(tty);
62
- wrote = true;
63
- } catch { /* terminal may not support direct device access */ }
64
-
65
- logHookActivity('set-terminal-title', 'UserPromptSubmit', wrote ? 'ok' : 'failed');
66
- } catch { /* fail-open */ }
67
-
68
- process.exit(0);
@@ -1,38 +0,0 @@
1
- {
2
- "sessionId": "",
3
- "feature": "",
4
- "phase": "",
5
- "hooks": [
6
- {
7
- "name": "set-terminal-title",
8
- "event": "UserPromptSubmit",
9
- "result": "failed",
10
- "ts": "16:06:20"
11
- },
12
- {
13
- "name": "set-terminal-title",
14
- "event": "UserPromptSubmit",
15
- "result": "failed",
16
- "ts": "16:12:07"
17
- },
18
- {
19
- "name": "set-terminal-title",
20
- "event": "UserPromptSubmit",
21
- "result": "failed",
22
- "ts": "16:12:15"
23
- },
24
- {
25
- "name": "set-terminal-title",
26
- "event": "UserPromptSubmit",
27
- "result": "failed",
28
- "ts": "16:12:15"
29
- },
30
- {
31
- "name": "set-terminal-title",
32
- "event": "UserPromptSubmit",
33
- "result": "failed",
34
- "ts": "16:12:40"
35
- }
36
- ],
37
- "skills": []
38
- }
@@ -1,14 +0,0 @@
1
- {
2
- "sessionId": "",
3
- "feature": "",
4
- "phase": "",
5
- "hooks": [
6
- {
7
- "name": "set-terminal-title",
8
- "event": "UserPromptSubmit",
9
- "result": "failed",
10
- "ts": "16:38:44"
11
- }
12
- ],
13
- "skills": []
14
- }