@polymorphism-tech/morph-spec 7.4.0 → 7.6.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/README.md +2 -2
- package/bin/morph-spec.js +18 -0
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +9 -4
- package/framework/MORPH.md +4 -4
- package/framework/agents.json +1 -1
- package/framework/commands/create-umbraco-lp.md +35 -0
- package/framework/commands/migrate-lp-to-umbraco.md +33 -0
- package/framework/commands/morph-archive.md +17 -27
- package/framework/commands/morph-preflight.md +10 -5
- package/framework/hooks/claude-code/core/enforce-phase-writes.js +115 -90
- package/framework/hooks/claude-code/core/protect-spec-files.js +32 -30
- package/framework/hooks/claude-code/core/state-sync.js +16 -48
- package/framework/hooks/shared/state-reader.js +74 -8
- package/framework/hooks/shared/state-writer.js +124 -0
- package/framework/rules/infrastructure-standards.md +4 -4
- package/framework/rules/morph-task-tracking.md +69 -49
- package/framework/rules/morph-workflow.md +192 -191
- package/framework/skills/core/create-umbraco-lp/SKILL.md +272 -0
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +531 -0
- package/framework/skills/core/morph-apply/SKILL.md +15 -15
- package/framework/skills/core/morph-brainstorming/SKILL.md +5 -5
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-implement/SKILL.md +5 -4
- package/framework/skills/core/morph-plan/SKILL.md +6 -6
- package/framework/skills/core/morph-proposal/SKILL.md +8 -7
- package/framework/skills/core/morph-review/SKILL.md +3 -3
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +80 -8
- package/framework/standards/ai-agents/durable-workflows-hitl.md +191 -0
- package/framework/standards/ai-agents/rag-custom-pgvector.md +246 -243
- package/framework/standards/ai-agents/setup.md +3 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +170 -0
- package/framework/standards/ai-agents/workflows.md +190 -187
- package/framework/standards/infrastructure/docker/{easypanel-deploy.md → coolify-deploy.md} +49 -20
- package/framework/templates/README.md +7 -7
- package/framework/templates/REGISTRY.json +15 -17
- package/framework/templates/context/CONTEXT-FEATURE.md +10 -17
- package/framework/templates/context/CONTEXT.md +181 -180
- package/framework/templates/docs/onboarding.md +122 -118
- package/framework/templates/docs/proposal.md +12 -2
- package/framework/templates/docs/spec.md +228 -228
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +1 -1
- package/framework/templates/infrastructure/docker/coolify.template.json +49 -0
- package/framework/templates/infrastructure/github/README.md +6 -6
- package/framework/templates/infrastructure/github/workflows/deploy-coolify.yml.hbs +33 -0
- package/framework/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -80
- package/framework/templates/meta-prompts/squad-leaders/backend-squad.md +90 -89
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +2 -1
- package/framework/templates/meta-prompts/squad-leaders/squad-leader.md +44 -43
- package/framework/templates/meta-prompts/validators/checkpoint-validator.md +107 -107
- package/package.json +1 -1
- package/src/commands/project/update.js +415 -368
- package/src/commands/project/worktree.js +212 -210
- package/src/commands/state/advance.js +82 -0
- package/src/commands/state/archive.js +111 -0
- package/src/commands/validation/validate-feature.js +229 -105
- package/src/core/state/state-manager.js +238 -66
- package/src/dashboard/scanner/state-scanner.js +35 -8
- package/src/lib/generators/context-generator.js +12 -8
- package/src/utils/file-copier.js +7 -0
- package/framework/templates/infrastructure/docker/easypanel.template.json +0 -46
- package/framework/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +0 -31
|
@@ -1,228 +1,228 @@
|
|
|
1
|
-
# Feature Specification: {{titleCase FEATURE_NAME}}
|
|
2
|
-
|
|
3
|
-
| Field | Value |
|
|
4
|
-
|-------|-------|
|
|
5
|
-
| **ID** | {{FEATURE_NAME}} |
|
|
6
|
-
| **Status** | Draft / In Review / Approved / In Progress / Done |
|
|
7
|
-
| **Created** | {{DATE}} |
|
|
8
|
-
| **Stack** | {{STACK}} |
|
|
9
|
-
| **Complexity** | Low / Medium / High |
|
|
10
|
-
| **Estimated Cost** | $X/month |
|
|
11
|
-
| **Agents** | Core: All / Specialists: {list} |
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Overview
|
|
16
|
-
|
|
17
|
-
**Problem:** {What problem this feature solves}
|
|
18
|
-
|
|
19
|
-
**Solution:** {High-level solution}
|
|
20
|
-
|
|
21
|
-
**Success Criteria:**
|
|
22
|
-
- [ ] {Criterion 1}
|
|
23
|
-
- [ ] {Criterion 2}
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Requirements
|
|
28
|
-
|
|
29
|
-
**Functional:** FR1: {desc} | FR2: {desc} | FR3: {desc}
|
|
30
|
-
|
|
31
|
-
**Non-Functional:** NFR1: Performance - {target} | NFR2: Reliability - {target}
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## User Stories
|
|
36
|
-
|
|
37
|
-
### US001: {Title}
|
|
38
|
-
**As** {user type} **I want** {feature} **so that** {benefit}
|
|
39
|
-
|
|
40
|
-
**Acceptance Criteria:** 1. {criterion} 2. {criterion}
|
|
41
|
-
|
|
42
|
-
**Edge Cases:** {edge case}: {handling}
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Technical
|
|
47
|
-
|
|
48
|
-
### Stack
|
|
49
|
-
| Component | Technology |
|
|
50
|
-
|-----------|------------|
|
|
51
|
-
| Frontend | {Next.js / .NET 10} |
|
|
52
|
-
| Backend | .NET 10 / C# 14 |
|
|
53
|
-
| Database | {Azure SQL / Cosmos DB} |
|
|
54
|
-
|
|
55
|
-
### Data Model
|
|
56
|
-
|
|
57
|
-
#### {EntityName}
|
|
58
|
-
| Column | Type | Constraints |
|
|
59
|
-
|--------|------|-------------|
|
|
60
|
-
| Id | Guid | PK |
|
|
61
|
-
| {Property} | {Type} | {Constraints} |
|
|
62
|
-
| CreatedAt | datetime2 | Default: GETUTCDATE() |
|
|
63
|
-
|
|
64
|
-
### Contracts
|
|
65
|
-
|
|
66
|
-
```csharp
|
|
67
|
-
public interface I{{pascalCase FEATURE_NAME}}Service
|
|
68
|
-
{
|
|
69
|
-
Task<{{pascalCase FEATURE_NAME}}Dto> GetByIdAsync(int id);
|
|
70
|
-
Task<{{pascalCase FEATURE_NAME}}Dto> CreateAsync(Create{{pascalCase FEATURE_NAME}}Request request);
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**Contracts Workflow:** Generate `contracts.cs` FIRST → validate names → reference in spec → approve with user.
|
|
75
|
-
|
|
76
|
-
**Validation Checklist:**
|
|
77
|
-
- [ ] Property names are descriptive (not generic "Data", "Value")
|
|
78
|
-
- [ ] Records use correct types (Stream vs byte[], Guid vs string)
|
|
79
|
-
- [ ] Response DTOs have all properties needed for UI
|
|
80
|
-
- [ ] Request DTOs have implicit validations (required, nullable)
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## Domain Complexity
|
|
85
|
-
|
|
86
|
-
**Nível:** {1 — CRUD / 2 — Business Logic / 3 — Bounded Context}
|
|
87
|
-
|
|
88
|
-
**Justificativa:** {Por que este nível foi escolhido — mencionar invariants, eventos ou BCs se Nível 2+}
|
|
89
|
-
|
|
90
|
-
**Padrões Aplicados:**
|
|
91
|
-
- {Nível 1: Entity simples, Service CRUD, DTOs}
|
|
92
|
-
- {Nível 2: AggregateRoot, Value Objects, Domain Events, CQRS}
|
|
93
|
-
- {Nível 3: Bounded Context isolation, cross-BC events, Linguagem Ubíqua}
|
|
94
|
-
|
|
95
|
-
**Padrões Omitidos:**
|
|
96
|
-
- {ex: Bounded Contexts — sistema single-domain}
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Architecture Style: Vertical Slice
|
|
101
|
-
|
|
102
|
-
> Preencher SOMENTE se `config.architecture.style === "vertical-slice"`. Omitir em projetos DDD.
|
|
103
|
-
|
|
104
|
-
**Architecture Style:** Vertical Slice Architecture (VSA)
|
|
105
|
-
|
|
106
|
-
**Entity Fields:**
|
|
107
|
-
| Field | Type | Constraints |
|
|
108
|
-
|-------|------|-------------|
|
|
109
|
-
| Id | Guid | PK, `Guid.CreateVersion7()` |
|
|
110
|
-
| {Field} | {C# Type} | {Required / Optional / Unique} |
|
|
111
|
-
| CreatedAt | DateTimeOffset | Auto |
|
|
112
|
-
|
|
113
|
-
**Operations:**
|
|
114
|
-
| Slice | HTTP | Route | Has Validator |
|
|
115
|
-
|-------|------|-------|---------------|
|
|
116
|
-
| Create{Entity} | POST | {ROUTE} | Yes |
|
|
117
|
-
| GetAll{Entity}s | GET | {ROUTE} | No |
|
|
118
|
-
| Get{Entity}ById | GET | {ROUTE}/{id} | Yes |
|
|
119
|
-
| Update{Entity} | PUT | {ROUTE}/{id} | Yes |
|
|
120
|
-
| Delete{Entity} | DELETE | {ROUTE}/{id} | Yes |
|
|
121
|
-
|
|
122
|
-
**Error Types ({Entity}Errors):**
|
|
123
|
-
- `{Entity}Errors.{ErrorName}()` — {description}
|
|
124
|
-
|
|
125
|
-
**Validation Rules:**
|
|
126
|
-
| Field | Rules |
|
|
127
|
-
|-------|-------|
|
|
128
|
-
| {Field} | NotEmpty(), MaxLength({N}), {etc.} |
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## Aggregate Blueprint (Nível 2+ apenas)
|
|
133
|
-
|
|
134
|
-
> Omitir esta seção se Nível 1 (CRUD) ou se Architecture Style = Vertical Slice.
|
|
135
|
-
|
|
136
|
-
### Aggregate Root: {EntityName}
|
|
137
|
-
|
|
138
|
-
**Invariants:**
|
|
139
|
-
- {Invariant 1 em linguagem natural}
|
|
140
|
-
- {Invariant 2}
|
|
141
|
-
|
|
142
|
-
**Estados e Transições:**
|
|
143
|
-
```
|
|
144
|
-
{Status.Draft} → Confirm() → {Status.Confirmed} → Cancel() → {Status.Cancelled}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
**Domain Events:**
|
|
148
|
-
- `{EntityName}CreatedEvent` — publicado ao criar
|
|
149
|
-
- `{EntityName}StatusChangedEvent` — publicado em mudança de estado
|
|
150
|
-
|
|
151
|
-
**Value Objects:**
|
|
152
|
-
- `{ValueObjectName}` — {por que não é primitivo simples}
|
|
153
|
-
|
|
154
|
-
**Referências Cross-Aggregate (por ID):**
|
|
155
|
-
- `{OtherEntity}Id: Guid`
|
|
156
|
-
|
|
157
|
-
### Linguagem Ubíqua
|
|
158
|
-
|
|
159
|
-
| Termo | Definição | Código |
|
|
160
|
-
|-------|-----------|--------|
|
|
161
|
-
| {Termo} | {Definição do negócio} | `{ClassName.MethodName()}` |
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## UI/UX Design (if front-end)
|
|
166
|
-
|
|
167
|
-
### Wireframes
|
|
168
|
-
```
|
|
169
|
-
{ASCII wireframe per screen - include states: loading, error, empty}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
### User Flow
|
|
173
|
-
1. {Step} → {System response}
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Flows
|
|
178
|
-
|
|
179
|
-
### {Flow Name}
|
|
180
|
-
**Trigger:** {what starts this flow}
|
|
181
|
-
1. {Actor} {action} → {system response}
|
|
182
|
-
2. If {condition}: Path A / Else: Path B
|
|
183
|
-
**End State:** {final state}
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## Cost Estimate
|
|
188
|
-
|
|
189
|
-
| Resource | SKU | Monthly Cost | Justification |
|
|
190
|
-
|----------|-----|--------------|---------------|
|
|
191
|
-
| {Resource} | {SKU} | ${X} | {Why} |
|
|
192
|
-
| **Total** | | **${X}/month** | |
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
## ADRs (Architectural Decision Records)
|
|
197
|
-
|
|
198
|
-
### ADR-001: {Decision Title}
|
|
199
|
-
**Status:** Proposed / Accepted
|
|
200
|
-
**Context:** {Why decide now}
|
|
201
|
-
**Decision:** {What we chose}
|
|
202
|
-
**Alternatives:** 1. {Alt} (pros/cons) 2. {Alt} (pros/cons)
|
|
203
|
-
**Trade-offs:** {key trade-offs}
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Security
|
|
208
|
-
|
|
209
|
-
| Action | Required Policy |
|
|
210
|
-
|--------|-----------------|
|
|
211
|
-
| View | CanView{Feature} |
|
|
212
|
-
| Create | CanManage{Feature} |
|
|
213
|
-
|
|
214
|
-
## Risks
|
|
215
|
-
|
|
216
|
-
| Risk | Impact | Mitigation |
|
|
217
|
-
|------|--------|------------|
|
|
218
|
-
| {Risk} | {H/M/L} | {Mitigation} |
|
|
219
|
-
|
|
220
|
-
## Out of Scope
|
|
221
|
-
- {Item}
|
|
222
|
-
|
|
223
|
-
## Definition of Done
|
|
224
|
-
- [ ] Code implemented
|
|
225
|
-
- [ ] Tests >80% coverage
|
|
226
|
-
- [ ] Code review approved
|
|
227
|
-
- [ ] Deploy to staging
|
|
228
|
-
- [ ] Recap.md generated
|
|
1
|
+
# Feature Specification: {{titleCase FEATURE_NAME}}
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| **ID** | {{FEATURE_NAME}} |
|
|
6
|
+
| **Status** | Draft / In Review / Approved / In Progress / Done |
|
|
7
|
+
| **Created** | {{DATE}} |
|
|
8
|
+
| **Stack** | {{STACK}} |
|
|
9
|
+
| **Complexity** | Low / Medium / High |
|
|
10
|
+
| **Estimated Cost** | $X/month |
|
|
11
|
+
| **Agents** | Core: All / Specialists: {list} |
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
**Problem:** {What problem this feature solves}
|
|
18
|
+
|
|
19
|
+
**Solution:** {High-level solution}
|
|
20
|
+
|
|
21
|
+
**Success Criteria:**
|
|
22
|
+
- [ ] {Criterion 1}
|
|
23
|
+
- [ ] {Criterion 2}
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
**Functional:** FR1: {desc} | FR2: {desc} | FR3: {desc}
|
|
30
|
+
|
|
31
|
+
**Non-Functional:** NFR1: Performance - {target} | NFR2: Reliability - {target}
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## User Stories
|
|
36
|
+
|
|
37
|
+
### US001: {Title}
|
|
38
|
+
**As** {user type} **I want** {feature} **so that** {benefit}
|
|
39
|
+
|
|
40
|
+
**Acceptance Criteria:** 1. {criterion} 2. {criterion}
|
|
41
|
+
|
|
42
|
+
**Edge Cases:** {edge case}: {handling}
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Technical Architecture
|
|
47
|
+
|
|
48
|
+
### Stack
|
|
49
|
+
| Component | Technology |
|
|
50
|
+
|-----------|------------|
|
|
51
|
+
| Frontend | {Next.js / .NET 10} |
|
|
52
|
+
| Backend | .NET 10 / C# 14 |
|
|
53
|
+
| Database | {Azure SQL / Cosmos DB} |
|
|
54
|
+
|
|
55
|
+
### Data Model
|
|
56
|
+
|
|
57
|
+
#### {EntityName}
|
|
58
|
+
| Column | Type | Constraints |
|
|
59
|
+
|--------|------|-------------|
|
|
60
|
+
| Id | Guid | PK |
|
|
61
|
+
| {Property} | {Type} | {Constraints} |
|
|
62
|
+
| CreatedAt | datetime2 | Default: GETUTCDATE() |
|
|
63
|
+
|
|
64
|
+
### Contracts
|
|
65
|
+
|
|
66
|
+
```csharp
|
|
67
|
+
public interface I{{pascalCase FEATURE_NAME}}Service
|
|
68
|
+
{
|
|
69
|
+
Task<{{pascalCase FEATURE_NAME}}Dto> GetByIdAsync(int id);
|
|
70
|
+
Task<{{pascalCase FEATURE_NAME}}Dto> CreateAsync(Create{{pascalCase FEATURE_NAME}}Request request);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Contracts Workflow:** Generate `contracts.cs` FIRST → validate names → reference in spec → approve with user.
|
|
75
|
+
|
|
76
|
+
**Validation Checklist:**
|
|
77
|
+
- [ ] Property names are descriptive (not generic "Data", "Value")
|
|
78
|
+
- [ ] Records use correct types (Stream vs byte[], Guid vs string)
|
|
79
|
+
- [ ] Response DTOs have all properties needed for UI
|
|
80
|
+
- [ ] Request DTOs have implicit validations (required, nullable)
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Domain Complexity
|
|
85
|
+
|
|
86
|
+
**Nível:** {1 — CRUD / 2 — Business Logic / 3 — Bounded Context}
|
|
87
|
+
|
|
88
|
+
**Justificativa:** {Por que este nível foi escolhido — mencionar invariants, eventos ou BCs se Nível 2+}
|
|
89
|
+
|
|
90
|
+
**Padrões Aplicados:**
|
|
91
|
+
- {Nível 1: Entity simples, Service CRUD, DTOs}
|
|
92
|
+
- {Nível 2: AggregateRoot, Value Objects, Domain Events, CQRS}
|
|
93
|
+
- {Nível 3: Bounded Context isolation, cross-BC events, Linguagem Ubíqua}
|
|
94
|
+
|
|
95
|
+
**Padrões Omitidos:**
|
|
96
|
+
- {ex: Bounded Contexts — sistema single-domain}
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Architecture Style: Vertical Slice
|
|
101
|
+
|
|
102
|
+
> Preencher SOMENTE se `config.architecture.style === "vertical-slice"`. Omitir em projetos DDD.
|
|
103
|
+
|
|
104
|
+
**Architecture Style:** Vertical Slice Architecture (VSA)
|
|
105
|
+
|
|
106
|
+
**Entity Fields:**
|
|
107
|
+
| Field | Type | Constraints |
|
|
108
|
+
|-------|------|-------------|
|
|
109
|
+
| Id | Guid | PK, `Guid.CreateVersion7()` |
|
|
110
|
+
| {Field} | {C# Type} | {Required / Optional / Unique} |
|
|
111
|
+
| CreatedAt | DateTimeOffset | Auto |
|
|
112
|
+
|
|
113
|
+
**Operations:**
|
|
114
|
+
| Slice | HTTP | Route | Has Validator |
|
|
115
|
+
|-------|------|-------|---------------|
|
|
116
|
+
| Create{Entity} | POST | {ROUTE} | Yes |
|
|
117
|
+
| GetAll{Entity}s | GET | {ROUTE} | No |
|
|
118
|
+
| Get{Entity}ById | GET | {ROUTE}/{id} | Yes |
|
|
119
|
+
| Update{Entity} | PUT | {ROUTE}/{id} | Yes |
|
|
120
|
+
| Delete{Entity} | DELETE | {ROUTE}/{id} | Yes |
|
|
121
|
+
|
|
122
|
+
**Error Types ({Entity}Errors):**
|
|
123
|
+
- `{Entity}Errors.{ErrorName}()` — {description}
|
|
124
|
+
|
|
125
|
+
**Validation Rules:**
|
|
126
|
+
| Field | Rules |
|
|
127
|
+
|-------|-------|
|
|
128
|
+
| {Field} | NotEmpty(), MaxLength({N}), {etc.} |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Aggregate Blueprint (Nível 2+ apenas)
|
|
133
|
+
|
|
134
|
+
> Omitir esta seção se Nível 1 (CRUD) ou se Architecture Style = Vertical Slice.
|
|
135
|
+
|
|
136
|
+
### Aggregate Root: {EntityName}
|
|
137
|
+
|
|
138
|
+
**Invariants:**
|
|
139
|
+
- {Invariant 1 em linguagem natural}
|
|
140
|
+
- {Invariant 2}
|
|
141
|
+
|
|
142
|
+
**Estados e Transições:**
|
|
143
|
+
```
|
|
144
|
+
{Status.Draft} → Confirm() → {Status.Confirmed} → Cancel() → {Status.Cancelled}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Domain Events:**
|
|
148
|
+
- `{EntityName}CreatedEvent` — publicado ao criar
|
|
149
|
+
- `{EntityName}StatusChangedEvent` — publicado em mudança de estado
|
|
150
|
+
|
|
151
|
+
**Value Objects:**
|
|
152
|
+
- `{ValueObjectName}` — {por que não é primitivo simples}
|
|
153
|
+
|
|
154
|
+
**Referências Cross-Aggregate (por ID):**
|
|
155
|
+
- `{OtherEntity}Id: Guid`
|
|
156
|
+
|
|
157
|
+
### Linguagem Ubíqua
|
|
158
|
+
|
|
159
|
+
| Termo | Definição | Código |
|
|
160
|
+
|-------|-----------|--------|
|
|
161
|
+
| {Termo} | {Definição do negócio} | `{ClassName.MethodName()}` |
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## UI/UX Design (if front-end)
|
|
166
|
+
|
|
167
|
+
### Wireframes
|
|
168
|
+
```
|
|
169
|
+
{ASCII wireframe per screen - include states: loading, error, empty}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### User Flow
|
|
173
|
+
1. {Step} → {System response}
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Flows
|
|
178
|
+
|
|
179
|
+
### {Flow Name}
|
|
180
|
+
**Trigger:** {what starts this flow}
|
|
181
|
+
1. {Actor} {action} → {system response}
|
|
182
|
+
2. If {condition}: Path A / Else: Path B
|
|
183
|
+
**End State:** {final state}
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Cost Estimate
|
|
188
|
+
|
|
189
|
+
| Resource | SKU | Monthly Cost | Justification |
|
|
190
|
+
|----------|-----|--------------|---------------|
|
|
191
|
+
| {Resource} | {SKU} | ${X} | {Why} |
|
|
192
|
+
| **Total** | | **${X}/month** | |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## ADRs (Architectural Decision Records)
|
|
197
|
+
|
|
198
|
+
### ADR-001: {Decision Title}
|
|
199
|
+
**Status:** Proposed / Accepted
|
|
200
|
+
**Context:** {Why decide now}
|
|
201
|
+
**Decision:** {What we chose}
|
|
202
|
+
**Alternatives:** 1. {Alt} (pros/cons) 2. {Alt} (pros/cons)
|
|
203
|
+
**Trade-offs:** {key trade-offs}
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Security
|
|
208
|
+
|
|
209
|
+
| Action | Required Policy |
|
|
210
|
+
|--------|-----------------|
|
|
211
|
+
| View | CanView{Feature} |
|
|
212
|
+
| Create | CanManage{Feature} |
|
|
213
|
+
|
|
214
|
+
## Risks
|
|
215
|
+
|
|
216
|
+
| Risk | Impact | Mitigation |
|
|
217
|
+
|------|--------|------------|
|
|
218
|
+
| {Risk} | {H/M/L} | {Mitigation} |
|
|
219
|
+
|
|
220
|
+
## Out of Scope
|
|
221
|
+
- {Item}
|
|
222
|
+
|
|
223
|
+
## Definition of Done
|
|
224
|
+
- [ ] Code implemented
|
|
225
|
+
- [ ] Tests >80% coverage
|
|
226
|
+
- [ ] Code review approved
|
|
227
|
+
- [ ] Deploy to staging
|
|
228
|
+
- [ ] Recap.md generated
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{kebabCase FEATURE_NAME}}",
|
|
3
|
+
"provider": "coolify",
|
|
4
|
+
"access": {
|
|
5
|
+
"method": "ssh",
|
|
6
|
+
"note": "No MCP/CLI exists for Coolify — replace sshHost with the real SSH alias for the target VPS. The API is reached only from inside the VPS, at apiBaseUrl.",
|
|
7
|
+
"sshHost": "REPLACE_WITH_VPS_SSH_ALIAS",
|
|
8
|
+
"apiBaseUrl": "http://localhost:8000/api/v1",
|
|
9
|
+
"tokenPath": "~/.coolify-token"
|
|
10
|
+
},
|
|
11
|
+
"application": {
|
|
12
|
+
"uuid": "REPLACE_WITH_COOLIFY_APPLICATION_UUID",
|
|
13
|
+
"projectUuid": "REPLACE_WITH_COOLIFY_PROJECT_UUID",
|
|
14
|
+
"serverUuid": "REPLACE_WITH_COOLIFY_SERVER_UUID"
|
|
15
|
+
},
|
|
16
|
+
"source": {
|
|
17
|
+
"type": "github",
|
|
18
|
+
"owner": "{{GITHUB_OWNER}}",
|
|
19
|
+
"repo": "{{GITHUB_REPO}}",
|
|
20
|
+
"branch": "main",
|
|
21
|
+
"autoDeploy": true
|
|
22
|
+
},
|
|
23
|
+
"build": {
|
|
24
|
+
"type": "dockerfile",
|
|
25
|
+
"dockerfile": "Dockerfile"
|
|
26
|
+
},
|
|
27
|
+
"deploy": {
|
|
28
|
+
"replicas": 1,
|
|
29
|
+
"zeroDowntime": true
|
|
30
|
+
},
|
|
31
|
+
"env": [
|
|
32
|
+
{
|
|
33
|
+
"key": "NODE_ENV",
|
|
34
|
+
"value": "production"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"key": "DATABASE_URL",
|
|
38
|
+
"value": "${DATABASE_URL}"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"domains": [
|
|
42
|
+
{
|
|
43
|
+
"host": "{{kebabCase FEATURE_NAME}}.example.com",
|
|
44
|
+
"port": 3000,
|
|
45
|
+
"https": true
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"deployCommand": "ssh REPLACE_WITH_VPS_SSH_ALIAS 'T=$(cat ~/.coolify-token); curl -s -X GET -H \"Authorization: Bearer $T\" \"http://localhost:8000/api/v1/deploy?uuid=REPLACE_WITH_COOLIFY_APPLICATION_UUID\"'"
|
|
49
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# GitHub Actions Templates for MORPH-SPEC
|
|
2
2
|
|
|
3
|
-
> **Framework-Level CI/CD Templates for
|
|
3
|
+
> **Framework-Level CI/CD Templates for Coolify/Docker Deployments**
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Reusable GitHub Actions workflows and composite actions for the **nextjs-neon** stack (
|
|
7
|
+
Reusable GitHub Actions workflows and composite actions for the **nextjs-neon** stack (Coolify/Docker deployment).
|
|
8
8
|
|
|
9
9
|
**Key Features:**
|
|
10
10
|
- Handlebars v2.0 templating with helpers
|
|
11
11
|
- Composite actions for shared logic
|
|
12
12
|
- Docker multi-stage builds (.NET API + Next.js Web)
|
|
13
|
-
-
|
|
13
|
+
- Coolify deployment via SSH (no MCP/CLI exists — the Coolify API is not publicly exposed, so the runner SSHes into the VPS to trigger it)
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ infrastructure/github/
|
|
|
21
21
|
├── workflows/
|
|
22
22
|
│ ├── dotnet-build.yml.hbs # .NET restore, build, test, coverage
|
|
23
23
|
│ ├── docker-build-push.yml.hbs # Docker build & push to registry
|
|
24
|
-
│ └── deploy-
|
|
24
|
+
│ └── deploy-coolify.yml.hbs # Coolify deployment via SSH
|
|
25
25
|
│
|
|
26
26
|
└── actions/
|
|
27
27
|
├── docker-build-push/action.yml.hbs # Build & push Docker image
|
|
@@ -38,8 +38,8 @@ infrastructure/github/
|
|
|
38
38
|
- Multi-stage Docker build
|
|
39
39
|
- Push to container registry (GHCR or Docker Hub)
|
|
40
40
|
|
|
41
|
-
### Deploy
|
|
42
|
-
-
|
|
41
|
+
### Deploy Coolify (`deploy-coolify.yml.hbs`)
|
|
42
|
+
- SSHes into the VPS and calls the local Coolify API (`localhost:8000/api/v1/deploy?uuid=...`) after Docker push
|
|
43
43
|
- Runs health check after deployment
|
|
44
44
|
- Supports staging + production environments
|
|
45
45
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Deploy to Coolify
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
environment:
|
|
7
|
+
required: true
|
|
8
|
+
type: string
|
|
9
|
+
image:
|
|
10
|
+
required: true
|
|
11
|
+
type: string
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
environment: ${{{{ inputs.environment }}}}
|
|
17
|
+
steps:
|
|
18
|
+
- name: Configure SSH
|
|
19
|
+
run: |
|
|
20
|
+
mkdir -p ~/.ssh
|
|
21
|
+
echo "${{{{ secrets.COOLIFY_SSH_KEY }}}}" > ~/.ssh/id_ed25519
|
|
22
|
+
chmod 600 ~/.ssh/id_ed25519
|
|
23
|
+
ssh-keyscan -H ${{{{ secrets.COOLIFY_SSH_HOST }}}} >> ~/.ssh/known_hosts
|
|
24
|
+
|
|
25
|
+
- name: Trigger Coolify Deploy (via SSH — the Coolify API is not publicly exposed)
|
|
26
|
+
run: |
|
|
27
|
+
ssh -i ~/.ssh/id_ed25519 ${{{{ secrets.COOLIFY_SSH_USER }}}}@${{{{ secrets.COOLIFY_SSH_HOST }}}} \
|
|
28
|
+
'T=$(cat ~/.coolify-token); curl -s -X GET -H "Authorization: Bearer $T" "http://localhost:8000/api/v1/deploy?uuid=${{{{ secrets.COOLIFY_APPLICATION_UUID }}}}"'
|
|
29
|
+
|
|
30
|
+
- name: Health Check
|
|
31
|
+
run: |
|
|
32
|
+
sleep 30 # Wait for deployment
|
|
33
|
+
curl --retry 10 --retry-delay 5 --retry-connrefused ${{{{ secrets.APP_URL }}}}/health
|