@polymorphism-tech/morph-spec 10.1.1 → 10.5.2
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/README.md +3 -7
- package/bin/morph-spec.js +10 -41
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -4
- package/docs/QUICKSTART.md +1 -1
- package/framework/MORPH.md +1 -1
- package/framework/agents.json +1 -2
- package/framework/commands/morph-archive.md +1 -1
- package/framework/commands/morph-preflight.md +3 -4
- package/framework/docs/CLI.md +45 -22
- package/framework/evals/review-checklist.md +5 -5
- package/framework/hooks/README.md +2 -2
- package/framework/hooks/claude-code/core/heavy-gate.js +21 -2
- package/framework/hooks/claude-code/core/validate-completion.js +0 -35
- package/framework/hooks/shared/e2e-check.js +44 -7
- package/framework/hooks/shared/heavy-command.js +12 -1
- package/framework/hooks/shared/heavy-config.js +12 -0
- package/framework/hooks/shared/host-services.js +9 -6
- package/framework/hooks/shared/next-step.js +12 -8
- package/framework/phases.json +4 -4
- package/framework/rules/plan-grammar.md +4 -1
- package/framework/schemas/config.schema.json +59 -1
- package/framework/schemas/feature.schema.json +15 -0
- 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 +8 -5
- package/framework/skills/core/morph-apply/references/hotfix.md +1 -1
- package/framework/skills/core/morph-apply/references/machine.md +3 -2
- package/framework/skills/core/morph-apply/references/review.md +9 -7
- package/framework/skills/core/morph-plan/SKILL.md +7 -6
- package/framework/skills/core/morph-plan/references/critique.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +2 -2
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/docs/plan.md +2 -1
- package/framework/templates/examples/design-system-examples.md +0 -3
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +1 -1
- package/src/commands/project/doctor.js +0 -1
- package/src/commands/project/heavy.js +13 -0
- package/src/commands/state/approve.js +9 -109
- package/src/commands/state/report-check.js +44 -2
- package/src/commands/validation/verify.js +57 -7
- package/src/core/state/state-manager.js +0 -24
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/heavy/cleanup.js +8 -2
- package/src/lib/heavy/gate.js +24 -1
- package/src/lib/heavy/reclaim.js +107 -0
- package/src/lib/heavy/watchdog.js +46 -0
- package/src/lib/next-step.js +1 -0
- package/src/lib/plan/checks.js +1 -1
- package/src/lib/plan/critique.js +23 -3
- package/src/lib/procs/prune.js +23 -1
- package/src/lib/review-confirmation.js +67 -0
- package/src/lib/review-reports.js +1 -0
- package/src/lib/risk-detector.js +2 -2
- package/src/lib/tasks/test-nodes.js +10 -0
- package/src/lib/tasks/test-runner.js +37 -43
- package/src/lib/telemetry/telemetry-reader.js +1 -2
- package/src/lib/telemetry/verify-event.js +7 -0
- package/src/lib/validators/verify-cache.js +63 -0
- package/src/lib/validators/verify-runner.js +131 -26
- package/src/lib/verify/affected.js +141 -0
- package/src/lib/verify/detached.js +154 -0
- package/src/utils/agents-installer.js +2 -2
- package/src/utils/hooks-installer.js +0 -20
- package/bin/validate.js +0 -212
- package/framework/hooks/claude-code/__pycache__/statusline.cpython-313.pyc +0 -0
- package/framework/templates/.idea/morph-templates.xml +0 -92
- package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
- package/src/commands/observability/telemetry.js +0 -60
- package/src/commands/validation/validate-feature.js +0 -337
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Design System - {Project Name}
|
|
3
|
-
*
|
|
4
|
-
* CSS Variables generated from design-system.md
|
|
5
|
-
* Use estas variáveis em todo o projeto para manter consistência visual.
|
|
6
|
-
*
|
|
7
|
-
* Template MORPH-SPEC by Polymorphism Tech
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
:root {
|
|
11
|
-
/* ========================================
|
|
12
|
-
* CORES PRINCIPAIS
|
|
13
|
-
* ======================================== */
|
|
14
|
-
|
|
15
|
-
--color-primary: #{hex da cor primária};
|
|
16
|
-
--color-primary-hover: #{hex da cor primária mais escura};
|
|
17
|
-
--color-primary-active: #{hex da cor primária ainda mais escura};
|
|
18
|
-
|
|
19
|
-
--color-secondary: #{hex da cor secundária};
|
|
20
|
-
--color-secondary-hover: #{hex};
|
|
21
|
-
--color-secondary-active: #{hex};
|
|
22
|
-
|
|
23
|
-
/* ========================================
|
|
24
|
-
* CORES DE ESTADO
|
|
25
|
-
* ======================================== */
|
|
26
|
-
|
|
27
|
-
--color-success: #{hex};
|
|
28
|
-
--color-success-bg: #{hex com transparência ou shade mais claro};
|
|
29
|
-
--color-success-border: #{hex};
|
|
30
|
-
|
|
31
|
-
--color-error: #{hex};
|
|
32
|
-
--color-error-bg: #{hex};
|
|
33
|
-
--color-error-border: #{hex};
|
|
34
|
-
|
|
35
|
-
--color-warning: #{hex};
|
|
36
|
-
--color-warning-bg: #{hex};
|
|
37
|
-
--color-warning-border: #{hex};
|
|
38
|
-
|
|
39
|
-
--color-info: #{hex};
|
|
40
|
-
--color-info-bg: #{hex};
|
|
41
|
-
--color-info-border: #{hex};
|
|
42
|
-
|
|
43
|
-
/* ========================================
|
|
44
|
-
* ESCALA DE NEUTROS (Cinzas)
|
|
45
|
-
* ======================================== */
|
|
46
|
-
|
|
47
|
-
--color-gray-50: #{hex};
|
|
48
|
-
--color-gray-100: #{hex};
|
|
49
|
-
--color-gray-200: #{hex};
|
|
50
|
-
--color-gray-300: #{hex};
|
|
51
|
-
--color-gray-400: #{hex};
|
|
52
|
-
--color-gray-500: #{hex};
|
|
53
|
-
--color-gray-600: #{hex};
|
|
54
|
-
--color-gray-700: #{hex};
|
|
55
|
-
--color-gray-800: #{hex};
|
|
56
|
-
--color-gray-900: #{hex};
|
|
57
|
-
|
|
58
|
-
/* ========================================
|
|
59
|
-
* TIPOGRAFIA - FONTES
|
|
60
|
-
* ======================================== */
|
|
61
|
-
|
|
62
|
-
--font-sans: '{Font Name}', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
|
63
|
-
--font-serif: '{Font Name}', Georgia, 'Times New Roman', serif;
|
|
64
|
-
--font-mono: '{Font Name}', 'Fira Code', 'Courier New', Consolas, monospace;
|
|
65
|
-
|
|
66
|
-
/* ========================================
|
|
67
|
-
* TIPOGRAFIA - TAMANHOS
|
|
68
|
-
* ======================================== */
|
|
69
|
-
|
|
70
|
-
--text-xs: 0.75rem; /* 12px */
|
|
71
|
-
--text-sm: 0.875rem; /* 14px */
|
|
72
|
-
--text-base: 1rem; /* 16px */
|
|
73
|
-
--text-lg: 1.125rem; /* 18px */
|
|
74
|
-
--text-xl: 1.25rem; /* 20px */
|
|
75
|
-
--text-2xl: 1.5rem; /* 24px */
|
|
76
|
-
--text-3xl: 1.875rem; /* 30px */
|
|
77
|
-
--text-4xl: 2.25rem; /* 36px */
|
|
78
|
-
--text-5xl: 3rem; /* 48px */
|
|
79
|
-
|
|
80
|
-
/* ========================================
|
|
81
|
-
* TIPOGRAFIA - LINE HEIGHTS
|
|
82
|
-
* ======================================== */
|
|
83
|
-
|
|
84
|
-
--leading-none: 1;
|
|
85
|
-
--leading-tight: 1.25;
|
|
86
|
-
--leading-snug: 1.375;
|
|
87
|
-
--leading-normal: 1.5;
|
|
88
|
-
--leading-relaxed: 1.625;
|
|
89
|
-
--leading-loose: 2;
|
|
90
|
-
|
|
91
|
-
/* ========================================
|
|
92
|
-
* TIPOGRAFIA - FONT WEIGHTS
|
|
93
|
-
* ======================================== */
|
|
94
|
-
|
|
95
|
-
--font-light: 300;
|
|
96
|
-
--font-regular: 400;
|
|
97
|
-
--font-medium: 500;
|
|
98
|
-
--font-semibold: 600;
|
|
99
|
-
--font-bold: 700;
|
|
100
|
-
--font-extrabold: 800;
|
|
101
|
-
|
|
102
|
-
/* ========================================
|
|
103
|
-
* ESPAÇAMENTO
|
|
104
|
-
* Baseado em múltiplos de {base}px (ex: 4px)
|
|
105
|
-
* ======================================== */
|
|
106
|
-
|
|
107
|
-
--space-0: 0;
|
|
108
|
-
--space-1: 0.25rem; /* 4px */
|
|
109
|
-
--space-2: 0.5rem; /* 8px */
|
|
110
|
-
--space-3: 0.75rem; /* 12px */
|
|
111
|
-
--space-4: 1rem; /* 16px */
|
|
112
|
-
--space-5: 1.25rem; /* 20px */
|
|
113
|
-
--space-6: 1.5rem; /* 24px */
|
|
114
|
-
--space-7: 1.75rem; /* 28px */
|
|
115
|
-
--space-8: 2rem; /* 32px */
|
|
116
|
-
--space-10: 2.5rem; /* 40px */
|
|
117
|
-
--space-12: 3rem; /* 48px */
|
|
118
|
-
--space-16: 4rem; /* 64px */
|
|
119
|
-
--space-20: 5rem; /* 80px */
|
|
120
|
-
--space-24: 6rem; /* 96px */
|
|
121
|
-
|
|
122
|
-
/* ========================================
|
|
123
|
-
* BORDER RADIUS
|
|
124
|
-
* ======================================== */
|
|
125
|
-
|
|
126
|
-
--rounded-none: 0;
|
|
127
|
-
--rounded-sm: 0.125rem; /* 2px */
|
|
128
|
-
--rounded-md: 0.375rem; /* 6px */
|
|
129
|
-
--rounded-lg: 0.5rem; /* 8px */
|
|
130
|
-
--rounded-xl: 0.75rem; /* 12px */
|
|
131
|
-
--rounded-2xl: 1rem; /* 16px */
|
|
132
|
-
--rounded-full: 9999px;
|
|
133
|
-
|
|
134
|
-
/* ========================================
|
|
135
|
-
* SOMBRAS (Shadows)
|
|
136
|
-
* ======================================== */
|
|
137
|
-
|
|
138
|
-
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
139
|
-
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
140
|
-
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
141
|
-
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
142
|
-
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
143
|
-
|
|
144
|
-
/* ========================================
|
|
145
|
-
* Z-INDEX LAYERS
|
|
146
|
-
* ======================================== */
|
|
147
|
-
|
|
148
|
-
--z-0: 0;
|
|
149
|
-
--z-10: 10;
|
|
150
|
-
--z-20: 20;
|
|
151
|
-
--z-30: 30;
|
|
152
|
-
--z-40: 40;
|
|
153
|
-
--z-50: 50; /* Modals, dropdowns */
|
|
154
|
-
--z-100: 100; /* Tooltips */
|
|
155
|
-
--z-max: 9999; /* Toasts, notifications */
|
|
156
|
-
|
|
157
|
-
/* ========================================
|
|
158
|
-
* TRANSITIONS / ANIMATIONS
|
|
159
|
-
* ======================================== */
|
|
160
|
-
|
|
161
|
-
--transition-fast: 150ms ease-in-out;
|
|
162
|
-
--transition-base: 250ms ease-in-out;
|
|
163
|
-
--transition-slow: 350ms ease-in-out;
|
|
164
|
-
|
|
165
|
-
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
166
|
-
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
167
|
-
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
168
|
-
|
|
169
|
-
/* ========================================
|
|
170
|
-
* BREAKPOINTS (informativo - usar em media queries)
|
|
171
|
-
* ======================================== */
|
|
172
|
-
|
|
173
|
-
/* @media (min-width: 640px) - sm */
|
|
174
|
-
/* @media (min-width: 768px) - md */
|
|
175
|
-
/* @media (min-width: 1024px) - lg */
|
|
176
|
-
/* @media (min-width: 1280px) - xl */
|
|
177
|
-
/* @media (min-width: 1536px) - 2xl */
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/* ========================================
|
|
181
|
-
* MODO ESCURO (Dark Mode)
|
|
182
|
-
* Opcional - ajuste as cores para dark theme
|
|
183
|
-
* ======================================== */
|
|
184
|
-
|
|
185
|
-
@media (prefers-color-scheme: dark) {
|
|
186
|
-
:root {
|
|
187
|
-
/* Inverter cores conforme necessário */
|
|
188
|
-
--color-gray-50: #{hex do gray-900};
|
|
189
|
-
--color-gray-900: #{hex do gray-50};
|
|
190
|
-
/* ... outras inversões */
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/* ========================================
|
|
195
|
-
* CLASSES UTILITÁRIAS (Exemplo)
|
|
196
|
-
* ======================================== */
|
|
197
|
-
|
|
198
|
-
/* Exemplo de uso das variáveis */
|
|
199
|
-
.btn-primary {
|
|
200
|
-
background-color: var(--color-primary);
|
|
201
|
-
color: white;
|
|
202
|
-
padding: var(--space-2) var(--space-4);
|
|
203
|
-
border-radius: var(--rounded-md);
|
|
204
|
-
font-weight: var(--font-semibold);
|
|
205
|
-
transition: background-color var(--transition-base);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.btn-primary:hover {
|
|
209
|
-
background-color: var(--color-primary-hover);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
.card {
|
|
213
|
-
background-color: white;
|
|
214
|
-
padding: var(--space-6);
|
|
215
|
-
border-radius: var(--rounded-lg);
|
|
216
|
-
box-shadow: var(--shadow-md);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
.text-muted {
|
|
220
|
-
color: var(--color-gray-600);
|
|
221
|
-
font-size: var(--text-sm);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/* ========================================
|
|
225
|
-
* FIM DO DESIGN SYSTEM
|
|
226
|
-
* ======================================== */
|
|
1
|
+
/**
|
|
2
|
+
* Design System - {Project Name}
|
|
3
|
+
*
|
|
4
|
+
* CSS Variables generated from design-system.md
|
|
5
|
+
* Use estas variáveis em todo o projeto para manter consistência visual.
|
|
6
|
+
*
|
|
7
|
+
* Template MORPH-SPEC by Polymorphism Tech
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
:root {
|
|
11
|
+
/* ========================================
|
|
12
|
+
* CORES PRINCIPAIS
|
|
13
|
+
* ======================================== */
|
|
14
|
+
|
|
15
|
+
--color-primary: #{hex da cor primária};
|
|
16
|
+
--color-primary-hover: #{hex da cor primária mais escura};
|
|
17
|
+
--color-primary-active: #{hex da cor primária ainda mais escura};
|
|
18
|
+
|
|
19
|
+
--color-secondary: #{hex da cor secundária};
|
|
20
|
+
--color-secondary-hover: #{hex};
|
|
21
|
+
--color-secondary-active: #{hex};
|
|
22
|
+
|
|
23
|
+
/* ========================================
|
|
24
|
+
* CORES DE ESTADO
|
|
25
|
+
* ======================================== */
|
|
26
|
+
|
|
27
|
+
--color-success: #{hex};
|
|
28
|
+
--color-success-bg: #{hex com transparência ou shade mais claro};
|
|
29
|
+
--color-success-border: #{hex};
|
|
30
|
+
|
|
31
|
+
--color-error: #{hex};
|
|
32
|
+
--color-error-bg: #{hex};
|
|
33
|
+
--color-error-border: #{hex};
|
|
34
|
+
|
|
35
|
+
--color-warning: #{hex};
|
|
36
|
+
--color-warning-bg: #{hex};
|
|
37
|
+
--color-warning-border: #{hex};
|
|
38
|
+
|
|
39
|
+
--color-info: #{hex};
|
|
40
|
+
--color-info-bg: #{hex};
|
|
41
|
+
--color-info-border: #{hex};
|
|
42
|
+
|
|
43
|
+
/* ========================================
|
|
44
|
+
* ESCALA DE NEUTROS (Cinzas)
|
|
45
|
+
* ======================================== */
|
|
46
|
+
|
|
47
|
+
--color-gray-50: #{hex};
|
|
48
|
+
--color-gray-100: #{hex};
|
|
49
|
+
--color-gray-200: #{hex};
|
|
50
|
+
--color-gray-300: #{hex};
|
|
51
|
+
--color-gray-400: #{hex};
|
|
52
|
+
--color-gray-500: #{hex};
|
|
53
|
+
--color-gray-600: #{hex};
|
|
54
|
+
--color-gray-700: #{hex};
|
|
55
|
+
--color-gray-800: #{hex};
|
|
56
|
+
--color-gray-900: #{hex};
|
|
57
|
+
|
|
58
|
+
/* ========================================
|
|
59
|
+
* TIPOGRAFIA - FONTES
|
|
60
|
+
* ======================================== */
|
|
61
|
+
|
|
62
|
+
--font-sans: '{Font Name}', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
|
63
|
+
--font-serif: '{Font Name}', Georgia, 'Times New Roman', serif;
|
|
64
|
+
--font-mono: '{Font Name}', 'Fira Code', 'Courier New', Consolas, monospace;
|
|
65
|
+
|
|
66
|
+
/* ========================================
|
|
67
|
+
* TIPOGRAFIA - TAMANHOS
|
|
68
|
+
* ======================================== */
|
|
69
|
+
|
|
70
|
+
--text-xs: 0.75rem; /* 12px */
|
|
71
|
+
--text-sm: 0.875rem; /* 14px */
|
|
72
|
+
--text-base: 1rem; /* 16px */
|
|
73
|
+
--text-lg: 1.125rem; /* 18px */
|
|
74
|
+
--text-xl: 1.25rem; /* 20px */
|
|
75
|
+
--text-2xl: 1.5rem; /* 24px */
|
|
76
|
+
--text-3xl: 1.875rem; /* 30px */
|
|
77
|
+
--text-4xl: 2.25rem; /* 36px */
|
|
78
|
+
--text-5xl: 3rem; /* 48px */
|
|
79
|
+
|
|
80
|
+
/* ========================================
|
|
81
|
+
* TIPOGRAFIA - LINE HEIGHTS
|
|
82
|
+
* ======================================== */
|
|
83
|
+
|
|
84
|
+
--leading-none: 1;
|
|
85
|
+
--leading-tight: 1.25;
|
|
86
|
+
--leading-snug: 1.375;
|
|
87
|
+
--leading-normal: 1.5;
|
|
88
|
+
--leading-relaxed: 1.625;
|
|
89
|
+
--leading-loose: 2;
|
|
90
|
+
|
|
91
|
+
/* ========================================
|
|
92
|
+
* TIPOGRAFIA - FONT WEIGHTS
|
|
93
|
+
* ======================================== */
|
|
94
|
+
|
|
95
|
+
--font-light: 300;
|
|
96
|
+
--font-regular: 400;
|
|
97
|
+
--font-medium: 500;
|
|
98
|
+
--font-semibold: 600;
|
|
99
|
+
--font-bold: 700;
|
|
100
|
+
--font-extrabold: 800;
|
|
101
|
+
|
|
102
|
+
/* ========================================
|
|
103
|
+
* ESPAÇAMENTO
|
|
104
|
+
* Baseado em múltiplos de {base}px (ex: 4px)
|
|
105
|
+
* ======================================== */
|
|
106
|
+
|
|
107
|
+
--space-0: 0;
|
|
108
|
+
--space-1: 0.25rem; /* 4px */
|
|
109
|
+
--space-2: 0.5rem; /* 8px */
|
|
110
|
+
--space-3: 0.75rem; /* 12px */
|
|
111
|
+
--space-4: 1rem; /* 16px */
|
|
112
|
+
--space-5: 1.25rem; /* 20px */
|
|
113
|
+
--space-6: 1.5rem; /* 24px */
|
|
114
|
+
--space-7: 1.75rem; /* 28px */
|
|
115
|
+
--space-8: 2rem; /* 32px */
|
|
116
|
+
--space-10: 2.5rem; /* 40px */
|
|
117
|
+
--space-12: 3rem; /* 48px */
|
|
118
|
+
--space-16: 4rem; /* 64px */
|
|
119
|
+
--space-20: 5rem; /* 80px */
|
|
120
|
+
--space-24: 6rem; /* 96px */
|
|
121
|
+
|
|
122
|
+
/* ========================================
|
|
123
|
+
* BORDER RADIUS
|
|
124
|
+
* ======================================== */
|
|
125
|
+
|
|
126
|
+
--rounded-none: 0;
|
|
127
|
+
--rounded-sm: 0.125rem; /* 2px */
|
|
128
|
+
--rounded-md: 0.375rem; /* 6px */
|
|
129
|
+
--rounded-lg: 0.5rem; /* 8px */
|
|
130
|
+
--rounded-xl: 0.75rem; /* 12px */
|
|
131
|
+
--rounded-2xl: 1rem; /* 16px */
|
|
132
|
+
--rounded-full: 9999px;
|
|
133
|
+
|
|
134
|
+
/* ========================================
|
|
135
|
+
* SOMBRAS (Shadows)
|
|
136
|
+
* ======================================== */
|
|
137
|
+
|
|
138
|
+
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
139
|
+
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
140
|
+
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
141
|
+
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
142
|
+
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
143
|
+
|
|
144
|
+
/* ========================================
|
|
145
|
+
* Z-INDEX LAYERS
|
|
146
|
+
* ======================================== */
|
|
147
|
+
|
|
148
|
+
--z-0: 0;
|
|
149
|
+
--z-10: 10;
|
|
150
|
+
--z-20: 20;
|
|
151
|
+
--z-30: 30;
|
|
152
|
+
--z-40: 40;
|
|
153
|
+
--z-50: 50; /* Modals, dropdowns */
|
|
154
|
+
--z-100: 100; /* Tooltips */
|
|
155
|
+
--z-max: 9999; /* Toasts, notifications */
|
|
156
|
+
|
|
157
|
+
/* ========================================
|
|
158
|
+
* TRANSITIONS / ANIMATIONS
|
|
159
|
+
* ======================================== */
|
|
160
|
+
|
|
161
|
+
--transition-fast: 150ms ease-in-out;
|
|
162
|
+
--transition-base: 250ms ease-in-out;
|
|
163
|
+
--transition-slow: 350ms ease-in-out;
|
|
164
|
+
|
|
165
|
+
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
166
|
+
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
167
|
+
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
168
|
+
|
|
169
|
+
/* ========================================
|
|
170
|
+
* BREAKPOINTS (informativo - usar em media queries)
|
|
171
|
+
* ======================================== */
|
|
172
|
+
|
|
173
|
+
/* @media (min-width: 640px) - sm */
|
|
174
|
+
/* @media (min-width: 768px) - md */
|
|
175
|
+
/* @media (min-width: 1024px) - lg */
|
|
176
|
+
/* @media (min-width: 1280px) - xl */
|
|
177
|
+
/* @media (min-width: 1536px) - 2xl */
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ========================================
|
|
181
|
+
* MODO ESCURO (Dark Mode)
|
|
182
|
+
* Opcional - ajuste as cores para dark theme
|
|
183
|
+
* ======================================== */
|
|
184
|
+
|
|
185
|
+
@media (prefers-color-scheme: dark) {
|
|
186
|
+
:root {
|
|
187
|
+
/* Inverter cores conforme necessário */
|
|
188
|
+
--color-gray-50: #{hex do gray-900};
|
|
189
|
+
--color-gray-900: #{hex do gray-50};
|
|
190
|
+
/* ... outras inversões */
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/* ========================================
|
|
195
|
+
* CLASSES UTILITÁRIAS (Exemplo)
|
|
196
|
+
* ======================================== */
|
|
197
|
+
|
|
198
|
+
/* Exemplo de uso das variáveis */
|
|
199
|
+
.btn-primary {
|
|
200
|
+
background-color: var(--color-primary);
|
|
201
|
+
color: white;
|
|
202
|
+
padding: var(--space-2) var(--space-4);
|
|
203
|
+
border-radius: var(--rounded-md);
|
|
204
|
+
font-weight: var(--font-semibold);
|
|
205
|
+
transition: background-color var(--transition-base);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.btn-primary:hover {
|
|
209
|
+
background-color: var(--color-primary-hover);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.card {
|
|
213
|
+
background-color: white;
|
|
214
|
+
padding: var(--space-6);
|
|
215
|
+
border-radius: var(--rounded-lg);
|
|
216
|
+
box-shadow: var(--shadow-md);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.text-muted {
|
|
220
|
+
color: var(--color-gray-600);
|
|
221
|
+
font-size: var(--text-sm);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ========================================
|
|
225
|
+
* FIM DO DESIGN SYSTEM
|
|
226
|
+
* ======================================== */
|
package/package.json
CHANGED
|
@@ -80,7 +80,6 @@ const REQUIRED_COMMAND_FILES = [
|
|
|
80
80
|
'src/commands/project/status.js',
|
|
81
81
|
'src/commands/project/worktree.js',
|
|
82
82
|
'src/commands/state/approve.js',
|
|
83
|
-
'src/commands/validation/validate-feature.js',
|
|
84
83
|
'src/commands/scaffold/scaffold.js',
|
|
85
84
|
'src/commands/mcp/mcp-setup.js',
|
|
86
85
|
'src/commands/context/context-refresh.js',
|
|
@@ -7,9 +7,22 @@ import { describeHolder, heavyDir, heavyStatus } from '../../../framework/hooks/
|
|
|
7
7
|
import { resolveSpawn } from '../../../framework/hooks/shared/spawn-command.js';
|
|
8
8
|
import { heavyClass, heavyKind } from '../../../framework/hooks/shared/heavy-command.js';
|
|
9
9
|
import { memoryBusyHint } from '../../lib/heavy/live-stacks.js';
|
|
10
|
+
import { reclaimUnlessDisabled } from '../../lib/heavy/reclaim.js';
|
|
10
11
|
|
|
11
12
|
const EXIT_BUSY = 3;
|
|
12
13
|
|
|
14
|
+
export function heavyReclaimCommand(options = {}) {
|
|
15
|
+
const projectPath = process.cwd();
|
|
16
|
+
const result = reclaimUnlessDisabled({ projectPath, config: readHeavyConfig(projectPath) });
|
|
17
|
+
if (options.json) {
|
|
18
|
+
console.log(JSON.stringify(result));
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
const gone = [...result.freed, ...result.containers];
|
|
22
|
+
console.log(gone.length ? `Derrubado: ${gone.join(', ')}` : 'Nada ocioso para derrubar.');
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
export function heavyStatusCommand(options = {}) {
|
|
14
27
|
const config = readHeavyConfig(process.cwd());
|
|
15
28
|
const status = heavyStatus({ dir: heavyDir(), maxHoldMs: config.maxHoldMinutes * 60_000 });
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import { join } from 'path';
|
|
6
|
-
import { getFeature, setApprovalGate, getApprovalGate, getApprovalHistory, derivePhase } from '../../core/state/state-manager.js';
|
|
4
|
+
import { getFeature, setApprovalGate, getApprovalGate } from '../../core/state/state-manager.js';
|
|
7
5
|
import { unmetPrereqs } from '../../core/state/gate-order.js';
|
|
8
6
|
import { reviewReports, reviewFileName, REVIEW_ROLES, VERDICT_TOKEN, REVIEWED_SHA_TOKEN } from '../../lib/review-reports.js';
|
|
9
7
|
import { shouldPauseGate } from '../../lib/risk-detector.js';
|
|
@@ -12,6 +10,7 @@ import { autoApprovalRefusal, printRefusal } from './auto-approval.js';
|
|
|
12
10
|
import { readTrustFromConfig } from './gate-decision.js';
|
|
13
11
|
import { assertOwnerTree, ownerTreeRefusalLines } from '../../lib/worktree/feature-truth.js';
|
|
14
12
|
import { treeMovedSince } from '../../lib/git/evidence-staleness.js';
|
|
13
|
+
import { reviewConfirmation } from '../../lib/review-confirmation.js';
|
|
15
14
|
import { seedDotnetBuildIgnores } from '../../lib/stack/dotnet-build-ignores.js';
|
|
16
15
|
import { reportDotnetIgnores } from './advance.js';
|
|
17
16
|
|
|
@@ -31,6 +30,11 @@ function reviewStaleness(reports) {
|
|
|
31
30
|
return { status: 'skip' };
|
|
32
31
|
}
|
|
33
32
|
|
|
33
|
+
const confirmation = reviewConfirmation(cwd, reports, head);
|
|
34
|
+
const excused = new Set(
|
|
35
|
+
confirmation.confirmed ? confirmation.moved.filter((m) => m.skippable).map((m) => m.role) : [],
|
|
36
|
+
);
|
|
37
|
+
|
|
34
38
|
let unstamped = null;
|
|
35
39
|
for (const [role, report] of Object.entries(reports)) {
|
|
36
40
|
if (report.status === 'missing') continue;
|
|
@@ -48,7 +52,7 @@ function reviewStaleness(reports) {
|
|
|
48
52
|
unstamped ??= { status: 'unstamped', file, head };
|
|
49
53
|
continue;
|
|
50
54
|
}
|
|
51
|
-
if (!treeMovedSince(cwd, reviewed, head)) continue;
|
|
55
|
+
if (excused.has(role) || !treeMovedSince(cwd, reviewed, head)) continue;
|
|
52
56
|
let ahead = 0;
|
|
53
57
|
try {
|
|
54
58
|
ahead = Number(execFileSync('git', ['rev-list', '--count', `${reviewed}..${head}`], { cwd, stdio: 'pipe' }).toString().trim()) || 0;
|
|
@@ -218,7 +222,7 @@ export async function approveCommand(featureName, gateName, options = {}) {
|
|
|
218
222
|
for (const role of unusable) {
|
|
219
223
|
const { status } = reports[role];
|
|
220
224
|
const what = status === 'missing' ? 'não existe'
|
|
221
|
-
: status === 'partial' ? 'está PARCIAL —
|
|
225
|
+
: status === 'partial' ? 'está PARCIAL — despache o mesmo papel de novo dizendo o que já está no relatório'
|
|
222
226
|
: `não tem \`${VERDICT_TOKEN} SHIP|FIX\``;
|
|
223
227
|
console.error(chalk.gray(` ${reviewFileName(role)} ${what}.`));
|
|
224
228
|
}
|
|
@@ -280,110 +284,6 @@ program
|
|
|
280
284
|
.description('Approve a phase gate to allow workflow progression')
|
|
281
285
|
.action(approveCommand);
|
|
282
286
|
|
|
283
|
-
export async function approvalStatusCommand(featureName, options = {}) {
|
|
284
|
-
try {
|
|
285
|
-
const feature = getFeature(featureName);
|
|
286
|
-
if (!feature) {
|
|
287
|
-
console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
|
|
288
|
-
process.exit(1);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Phase derived from the filesystem + approved gates, never "unknown".
|
|
292
|
-
const featurePath = join(process.cwd(), '.morph', 'features', featureName);
|
|
293
|
-
const phase = feature.phase || derivePhase(featurePath);
|
|
294
|
-
|
|
295
|
-
// The uiux branch is optional: a feature that never took it has no
|
|
296
|
-
// 1-design/ folder and no uiux approval — that is "n/a", not "rejected".
|
|
297
|
-
const uiuxGate = getApprovalGate(featureName, 'uiux');
|
|
298
|
-
const uiuxTaken = uiuxGate?.approved === true || existsSync(join(featurePath, '1-design'));
|
|
299
|
-
|
|
300
|
-
if (options.json) {
|
|
301
|
-
const status = {
|
|
302
|
-
feature: featureName,
|
|
303
|
-
phase,
|
|
304
|
-
status: feature.status,
|
|
305
|
-
uiuxTaken,
|
|
306
|
-
gates: {}
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
for (const gateName of VALID_GATES) {
|
|
310
|
-
status.gates[gateName] = getApprovalGate(featureName, gateName) || { approved: false };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
console.log(JSON.stringify(status, null, 2));
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
console.log(chalk.bold(`\n📋 Approval Status for: ${featureName}`));
|
|
318
|
-
console.log('━'.repeat(60));
|
|
319
|
-
|
|
320
|
-
console.log(chalk.cyan(`\nCurrent Phase: ${phase}`));
|
|
321
|
-
console.log(chalk.gray(`Feature Status: ${feature.status || 'unknown'}\n`));
|
|
322
|
-
|
|
323
|
-
console.log(chalk.bold('Approval Gates:'));
|
|
324
|
-
|
|
325
|
-
for (const gateName of VALID_GATES) {
|
|
326
|
-
const gateStatus = getApprovalGate(featureName, gateName);
|
|
327
|
-
|
|
328
|
-
if (!gateStatus) {
|
|
329
|
-
console.log(` ${chalk.gray('○')} ${gateName}: ${chalk.gray('Not yet evaluated')}`);
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (gateName === 'uiux' && !uiuxTaken) {
|
|
334
|
-
console.log(` ${chalk.gray('—')} ${gateName}: ${chalk.gray('n/a (ramo de design não tomado)')}`);
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (gateStatus.approved) {
|
|
339
|
-
console.log(` ${chalk.green('✓')} ${gateName}: ${chalk.green('Approved')}`);
|
|
340
|
-
if (gateStatus.timestamp) {
|
|
341
|
-
console.log(chalk.gray(` Approved at: ${gateStatus.timestamp}`));
|
|
342
|
-
}
|
|
343
|
-
if (gateStatus.approvedBy) {
|
|
344
|
-
console.log(chalk.gray(` Approved by: ${gateStatus.approvedBy}`));
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
// Distinguish "never evaluated" (initialized approved:false, no
|
|
348
|
-
// timestamp) from an explicit rejection/revocation (has timestamp).
|
|
349
|
-
const neverEvaluated = !gateStatus.timestamp && !gateStatus.rejectedAt && !gateStatus.revokedAt;
|
|
350
|
-
if (neverEvaluated) {
|
|
351
|
-
console.log(` ${chalk.gray('○')} ${gateName}: ${chalk.gray('Pending (not yet evaluated)')}`);
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
console.log(` ${chalk.red('✗')} ${gateName}: ${chalk.red('Rejected / Revoked')}`);
|
|
355
|
-
if (gateStatus.reason) {
|
|
356
|
-
console.log(chalk.gray(` Reason: ${gateStatus.reason}`));
|
|
357
|
-
}
|
|
358
|
-
if (gateStatus.timestamp) {
|
|
359
|
-
console.log(chalk.gray(` Rejected at: ${gateStatus.timestamp}`));
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const history = getApprovalHistory(featureName);
|
|
365
|
-
if (history && history.length > 0) {
|
|
366
|
-
console.log(chalk.bold('\nApproval History:'));
|
|
367
|
-
history.slice(-5).forEach(entry => {
|
|
368
|
-
const status = entry.approved ? chalk.green('✓ Approved') : chalk.red('✗ Rejected');
|
|
369
|
-
console.log(` ${status} ${entry.gate} - ${entry.timestamp}`);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
console.log('\n' + '━'.repeat(60) + '\n');
|
|
374
|
-
|
|
375
|
-
} catch (error) {
|
|
376
|
-
console.error(chalk.red(`\n❌ Error showing approval status: ${error.message}\n`));
|
|
377
|
-
process.exit(1);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
program
|
|
382
|
-
.command('approval-status <feature>')
|
|
383
|
-
.alias('status')
|
|
384
|
-
.description('Show approval status for all gates')
|
|
385
|
-
.action(approvalStatusCommand);
|
|
386
|
-
|
|
387
287
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
388
288
|
if (process.argv.length > 2) {
|
|
389
289
|
program.parse(process.argv);
|