sedd 0.1.8 → 0.1.10
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 +140 -2
- package/commands/sedd.board.md +67 -0
- package/commands/sedd.clarify.md +86 -21
- package/commands/sedd.specify.md +27 -1
- package/dist/cli/board.d.ts +9 -0
- package/dist/cli/board.d.ts.map +1 -0
- package/dist/cli/board.js +211 -0
- package/dist/cli/board.js.map +1 -0
- package/dist/cli/clarify.d.ts +5 -1
- package/dist/cli/clarify.d.ts.map +1 -1
- package/dist/cli/clarify.js +52 -8
- package/dist/cli/clarify.js.map +1 -1
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup-github.d.ts +5 -0
- package/dist/cli/setup-github.d.ts.map +1 -0
- package/dist/cli/setup-github.js +437 -0
- package/dist/cli/setup-github.js.map +1 -0
- package/dist/cli/specify.d.ts +1 -0
- package/dist/cli/specify.d.ts.map +1 -1
- package/dist/cli/specify.js +97 -9
- package/dist/cli/specify.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +31 -0
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/tasks.d.ts.map +1 -1
- package/dist/cli/tasks.js +102 -1
- package/dist/cli/tasks.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +21 -0
- package/dist/cli/update.js.map +1 -1
- package/dist/core/board-manager.d.ts +65 -0
- package/dist/core/board-manager.d.ts.map +1 -0
- package/dist/core/board-manager.js +326 -0
- package/dist/core/board-manager.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +117 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -1
- package/dist/utils/github.d.ts +99 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +488 -0
- package/dist/utils/github.js.map +1 -0
- package/package.json +61 -61
package/README.md
CHANGED
|
@@ -179,9 +179,22 @@ Criar migration de follow-up? [Y/n]
|
|
|
179
179
|
|---------|-----------|
|
|
180
180
|
| `sedd init` | Inicializar SEDD no projeto |
|
|
181
181
|
| `sedd specify <id> <name>` | Criar nova feature spec |
|
|
182
|
+
| `sedd specify <id> <name> --from-issue <url>` | Criar feature a partir de GitHub issue (baixa imagens) |
|
|
182
183
|
| `sedd clarify` | Criar migration com decisões |
|
|
184
|
+
| `sedd clarify --from-issue <url>` | Pre-popular migration com dados de GitHub issue (baixa imagens) |
|
|
183
185
|
| `sedd status` | Ver status atual |
|
|
186
|
+
| `sedd check` | Verificar estrutura e pre-requisitos |
|
|
187
|
+
| `sedd tasks <json>` | Adicionar tasks a migration atual |
|
|
188
|
+
| `sedd complete <task-id>` | Marcar task como concluida |
|
|
189
|
+
| `sedd estimate` | Estimar esforco da feature atual |
|
|
190
|
+
| `sedd validate` | Validar implementacao contra expectativa |
|
|
191
|
+
| `sedd board` | Kanban board no terminal |
|
|
184
192
|
| `sedd update` | Atualizar templates e migrar features existentes |
|
|
193
|
+
| `sedd migrate` | Migrar specs legados para nova estrutura |
|
|
194
|
+
| `sedd github setup` | Configurar integracao com GitHub Projects |
|
|
195
|
+
| `sedd github status` | Ver status da integracao GitHub |
|
|
196
|
+
| `sedd github sync` | Forcar sync bidirecional com GitHub |
|
|
197
|
+
| `sedd github refresh` | Re-ler colunas do projeto GitHub |
|
|
185
198
|
|
|
186
199
|
## Slash Commands (AI)
|
|
187
200
|
|
|
@@ -194,6 +207,9 @@ Criar migration de follow-up? [Y/n]
|
|
|
194
207
|
| `/sedd.dashboard` | Ver status atual de migrations e tasks |
|
|
195
208
|
| `/sedd.estimate` | Estimar prazo e complexidade antes de começar |
|
|
196
209
|
| `/sedd.validate` | Validar implementação contra expectativa |
|
|
210
|
+
| `/sedd.board` | Ver kanban board da feature |
|
|
211
|
+
| `/sedd.tasks` | Gerar tasks para migration |
|
|
212
|
+
| `/sedd.migrate` | Migrar specs legados |
|
|
197
213
|
|
|
198
214
|
---
|
|
199
215
|
|
|
@@ -318,12 +334,16 @@ Gaps: 1 encontrado
|
|
|
318
334
|
.sedd/001-user-auth/
|
|
319
335
|
├── spec.md # Especificação + Expectativa
|
|
320
336
|
├── _meta.json # Metadados + expectation estruturada
|
|
337
|
+
├── assets/ # Imagens baixadas de GitHub issues
|
|
338
|
+
│ ├── image-001.png
|
|
339
|
+
│ └── image-002.jpg
|
|
321
340
|
│
|
|
322
341
|
├── 001_timestamp/ # Migration 1
|
|
323
342
|
│ ├── clarify.md # Discussão + DEVE/NÃO DEVE
|
|
324
343
|
│ ├── decisions.md # Decisões
|
|
325
344
|
│ ├── tasks.md # Tasks T001-XXX
|
|
326
|
-
│
|
|
345
|
+
│ ├── acceptance.md # Critérios positivos e negativos
|
|
346
|
+
│ └── assets/ # Imagens de --from-issue no clarify
|
|
327
347
|
│
|
|
328
348
|
└── progress.md # Progresso + checkpoints + desvios
|
|
329
349
|
```
|
|
@@ -365,6 +385,114 @@ Pending tasks:
|
|
|
365
385
|
|
|
366
386
|
---
|
|
367
387
|
|
|
388
|
+
## GitHub Integration
|
|
389
|
+
|
|
390
|
+
SEDD integra com GitHub Projects V2 para sincronizar tasks como issues e gerenciar status via kanban board.
|
|
391
|
+
|
|
392
|
+
### Passo a passo
|
|
393
|
+
|
|
394
|
+
**1. Instalar GitHub CLI**
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Windows
|
|
398
|
+
winget install GitHub.cli
|
|
399
|
+
|
|
400
|
+
# Mac
|
|
401
|
+
brew install gh
|
|
402
|
+
|
|
403
|
+
# Linux
|
|
404
|
+
sudo apt install gh
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
**2. Autenticar**
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
gh auth login
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Selecione as opcoes:
|
|
414
|
+
- `GitHub.com`
|
|
415
|
+
- `HTTPS`
|
|
416
|
+
- `Login with a web browser`
|
|
417
|
+
|
|
418
|
+
O terminal vai mostrar um codigo (ex: `XXXX-XXXX`). Copie o codigo no terminal e cole no navegador quando solicitado.
|
|
419
|
+
|
|
420
|
+
Verifique:
|
|
421
|
+
```bash
|
|
422
|
+
gh auth status
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**3. Adicionar scope de projetos**
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
gh auth refresh -s project
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
O terminal vai mostrar outro codigo. Mesmo processo: copie no terminal e cole no navegador.
|
|
432
|
+
|
|
433
|
+
**4. Ter um GitHub Project**
|
|
434
|
+
|
|
435
|
+
Va em github.com > seu repo > Projects > New Project > Board.
|
|
436
|
+
Crie colunas como: Todo, In Progress, Done.
|
|
437
|
+
|
|
438
|
+
**5. Configurar SEDD**
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
sedd github setup
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
O setup interativo vai:
|
|
445
|
+
- Detectar seu repositorio
|
|
446
|
+
- Listar suas organizacoes e conta pessoal
|
|
447
|
+
- Permitir escolher o owner dos projetos
|
|
448
|
+
- Listar projetos disponiveis
|
|
449
|
+
- Mapear colunas do board
|
|
450
|
+
|
|
451
|
+
### Comandos GitHub
|
|
452
|
+
|
|
453
|
+
| Comando | Descricao |
|
|
454
|
+
|---------|-----------|
|
|
455
|
+
| `sedd github setup` | Configuracao interativa |
|
|
456
|
+
| `sedd github status` | Ver config e testar conexao |
|
|
457
|
+
| `sedd github sync` | Forcar sync bidirecional |
|
|
458
|
+
| `sedd github refresh` | Re-ler colunas se mudaram no GitHub |
|
|
459
|
+
| `sedd board` | Kanban board no terminal |
|
|
460
|
+
|
|
461
|
+
### Funcionalidades
|
|
462
|
+
|
|
463
|
+
- Use `--from-issue <url>` no `sedd specify` ou `sedd clarify` para criar features/migrations a partir de GitHub issues
|
|
464
|
+
- Imagens da issue sao baixadas automaticamente para `assets/` e os links reescritos para paths relativos, permitindo que a AI veja o conteudo visual
|
|
465
|
+
- Use `sedd board` para visualizar o kanban no terminal
|
|
466
|
+
- Multi-org: escolha entre suas organizacoes e conta pessoal durante o setup
|
|
467
|
+
|
|
468
|
+
### From Issue com Download de Imagens
|
|
469
|
+
|
|
470
|
+
Ao usar `--from-issue`, o SEDD automaticamente:
|
|
471
|
+
|
|
472
|
+
1. Busca titulo, body e labels da issue
|
|
473
|
+
2. Detecta imagens no body (`.png`, `.jpg`, `.gif`, `.webp`, `.svg` e `github.com/user-attachments`)
|
|
474
|
+
3. Baixa cada imagem para `assets/` dentro do diretorio da feature/migration
|
|
475
|
+
4. Reescreve os links markdown para paths relativos (`./assets/image-001.png`)
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
sedd specify 042 from-issue --from-issue https://github.com/org/repo/issues/42
|
|
479
|
+
|
|
480
|
+
✓ Issue #42: Add dark mode toggle
|
|
481
|
+
✓ Downloaded 3 images to assets/
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Resultado no `spec.md`:
|
|
485
|
+
```markdown
|
|
486
|
+

|
|
487
|
+

|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Isso permite que a AI veja o conteudo visual das imagens via Read tool, em vez de apenas a URL como texto.
|
|
491
|
+
|
|
492
|
+
Se o download de alguma imagem falhar, o link original e mantido.
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
368
496
|
## Configuração
|
|
369
497
|
|
|
370
498
|
`sedd.config.json`:
|
|
@@ -373,7 +501,17 @@ Pending tasks:
|
|
|
373
501
|
{
|
|
374
502
|
"specsDir": ".sedd",
|
|
375
503
|
"branchPattern": "{{id}}-{{name}}",
|
|
376
|
-
"scriptRunner": "auto"
|
|
504
|
+
"scriptRunner": "auto",
|
|
505
|
+
"github": {
|
|
506
|
+
"engine": "both",
|
|
507
|
+
"owner": "user",
|
|
508
|
+
"repo": "my-project",
|
|
509
|
+
"project": {
|
|
510
|
+
"projectNumber": 3,
|
|
511
|
+
"projectId": "PVT_...",
|
|
512
|
+
"title": "My Kanban"
|
|
513
|
+
}
|
|
514
|
+
}
|
|
377
515
|
}
|
|
378
516
|
```
|
|
379
517
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# /sedd.board — View Kanban Board
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Display the kanban board for the current feature, showing task status across columns (Todo, In Progress, Done). Provides WIP limit warnings and suggests the next task to work on.
|
|
5
|
+
|
|
6
|
+
## When to Use
|
|
7
|
+
- To visualize the current state of tasks in a feature migration
|
|
8
|
+
- To check WIP limits and flow health
|
|
9
|
+
- To see suggestions for what to work on next
|
|
10
|
+
- To sync task status with GitHub Projects
|
|
11
|
+
|
|
12
|
+
## Pre-flight Checks
|
|
13
|
+
1. Must be in a SEDD project (`.sedd/` directory exists)
|
|
14
|
+
2. Must have at least one feature with tasks
|
|
15
|
+
3. For GitHub sync: `sedd.config.json` must have `github.engine` set to `github` or `both`
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
### View current feature board
|
|
20
|
+
```bash
|
|
21
|
+
sedd board
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### View all feature boards
|
|
25
|
+
```bash
|
|
26
|
+
sedd board --all
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### JSON output (for programmatic use)
|
|
30
|
+
```bash
|
|
31
|
+
sedd board --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Move a task to a different column
|
|
35
|
+
```bash
|
|
36
|
+
sedd board --move T001-001 "In Progress"
|
|
37
|
+
sedd board --move T001-002 "Done"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Sync board with GitHub
|
|
41
|
+
```bash
|
|
42
|
+
sedd board --sync
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Board Layout
|
|
46
|
+
```
|
|
47
|
+
Kanban: 001-my-feature (Migration 003)
|
|
48
|
+
|
|
49
|
+
Todo [2/5] In Progress [1/3] Done [4]
|
|
50
|
+
───────────── ───────────── ─────────
|
|
51
|
+
T003-004 Setup DB T003-002 Auth API T003-001 Init
|
|
52
|
+
T003-005 Tests T003-003 Schema
|
|
53
|
+
|
|
54
|
+
WIP: OK
|
|
55
|
+
Next: T003-004 "Setup DB" (Next in queue)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Workflow
|
|
59
|
+
1. Run `/sedd.board` to see current status
|
|
60
|
+
2. When starting a task: `sedd board --move T001-001 "In Progress"`
|
|
61
|
+
3. When completing a task: `sedd complete T001-001` (auto-moves to Done)
|
|
62
|
+
4. If using GitHub: `sedd board --sync` to push changes to the project board
|
|
63
|
+
|
|
64
|
+
## Notes
|
|
65
|
+
- Works in local mode (no GitHub) by reading tasks.md directly
|
|
66
|
+
- WIP limits are optional, configured via `sedd github setup`
|
|
67
|
+
- Suggestions use a Lean algorithm: prioritize finishing in-progress work, then pick the next task in queue
|
package/commands/sedd.clarify.md
CHANGED
|
@@ -51,26 +51,67 @@ User runs `/sedd.clarify`
|
|
|
51
51
|
- Every migration has tasks.md (generated at the end)
|
|
52
52
|
- Tasks reference this migration ID
|
|
53
53
|
|
|
54
|
+
⚠️ **ANNOTATE EVERYTHING - TUDO VIRA TASK**
|
|
55
|
+
- Cada ponto do usuario → anotar como fonte de task
|
|
56
|
+
- Cada sugestao da AI aceita → anotar como fonte de task
|
|
57
|
+
- Cada decisao tomada → anotar implicacoes como fontes de task
|
|
58
|
+
- Cada edge case levantado → anotar como fonte de task
|
|
59
|
+
- Formato: **[TASK_SOURCE:{tipo}]** antes de cada ponto anotado
|
|
60
|
+
- Tipos: user-req, ai-suggestion, decision, edge-case, constraint
|
|
61
|
+
|
|
54
62
|
## Workflow
|
|
55
63
|
|
|
56
|
-
### Step 1:
|
|
64
|
+
### Step 1: Load Context PRIMEIRO
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
Read from feature root:
|
|
67
|
+
- spec.md (especialmente `## Expectation` e user stories)
|
|
68
|
+
- interfaces.ts (entidades)
|
|
69
|
+
- _meta.json (expectation do specify)
|
|
70
|
+
- Previous migrations (if any)
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
🎯 Qual é sua EXPECTATIVA para esta clarificação?
|
|
72
|
+
### Step 1.5: Suggest Expectations (PROACTIVE)
|
|
62
73
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
Com base no contexto carregado, AI DEVE:
|
|
75
|
+
|
|
76
|
+
1. Apresentar a expectativa original da spec:
|
|
77
|
+
> "Expectativa original (da spec): {quote}"
|
|
78
|
+
|
|
79
|
+
2. SUGERIR expectativas adicionais para esta migration baseado em:
|
|
80
|
+
- User stories nao cobertas por migrations anteriores
|
|
81
|
+
- Edge cases identificados nas interfaces
|
|
82
|
+
- Dependencias entre entidades
|
|
83
|
+
- Potenciais problemas de performance/seguranca
|
|
84
|
+
- Gaps entre a expectativa original e o que ja foi implementado
|
|
85
|
+
|
|
86
|
+
3. Apresentar assim:
|
|
87
|
+
```
|
|
88
|
+
Com base na spec e no que ja temos, sugiro para esta migration:
|
|
89
|
+
|
|
90
|
+
DEVE:
|
|
91
|
+
- [sugestao 1 baseada na spec]
|
|
92
|
+
- [sugestao 2 baseada em edge case]
|
|
93
|
+
- [sugestao 3 baseada em dependencia]
|
|
94
|
+
|
|
95
|
+
NAO DEVE:
|
|
96
|
+
- [restricao identificada]
|
|
97
|
+
|
|
98
|
+
Potenciais que identifiquei:
|
|
99
|
+
- [concern 1]
|
|
100
|
+
- [concern 2]
|
|
101
|
+
|
|
102
|
+
Quer acrescentar algo? Quer que eu veja outro potencial?
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
4. Aguardar usuario confirmar, ajustar, ou adicionar
|
|
106
|
+
5. SO ENTAO consolidar expectativa final (summary + must + mustNot)
|
|
66
107
|
|
|
67
108
|
Save in `clarify.md` under `## Expected Outcome` section (NO TOPO).
|
|
68
109
|
|
|
69
|
-
**NÃO PROSSIGA** sem a expectativa do usuário.
|
|
110
|
+
**NÃO PROSSIGA** sem a expectativa do usuário confirmada.
|
|
70
111
|
|
|
71
|
-
### Step
|
|
112
|
+
### Step 2: Detail MUST and MUST NOT (STRUCTURED EXPECTATION)
|
|
72
113
|
|
|
73
|
-
Após
|
|
114
|
+
Após consolidar as expectativas (originais + sugeridas + usuario), detalhar com regras claras:
|
|
74
115
|
|
|
75
116
|
```
|
|
76
117
|
Agora vamos detalhar sua expectativa:
|
|
@@ -111,13 +152,6 @@ Save in `clarify.md` under `## Expectation Details`:
|
|
|
111
152
|
}
|
|
112
153
|
```
|
|
113
154
|
|
|
114
|
-
### Step 2: Load Context
|
|
115
|
-
|
|
116
|
-
Read from feature root:
|
|
117
|
-
- spec.md (especialmente a seção Expectation original)
|
|
118
|
-
- interfaces.ts
|
|
119
|
-
- Previous migrations (if any)
|
|
120
|
-
|
|
121
155
|
### Step 3: Create New Migration Folder
|
|
122
156
|
|
|
123
157
|
Generate new migration folder:
|
|
@@ -199,9 +233,10 @@ When user provides information (not a command):
|
|
|
199
233
|
"O sistema precisa suportar múltiplos tenants, cada um com suas próprias configurações..."
|
|
200
234
|
|
|
201
235
|
**Key Points Extracted:**
|
|
202
|
-
- Multi-tenant architecture required
|
|
203
|
-
- Per-tenant configuration
|
|
204
|
-
- Isolation
|
|
236
|
+
- **[TASK_SOURCE:user-req]** Multi-tenant architecture required
|
|
237
|
+
- **[TASK_SOURCE:user-req]** Per-tenant configuration
|
|
238
|
+
- **[TASK_SOURCE:ai-suggestion]** Isolation strategy needs definition
|
|
239
|
+
- **[TASK_SOURCE:edge-case]** Cross-tenant data leaks prevention
|
|
205
240
|
|
|
206
241
|
---
|
|
207
242
|
```
|
|
@@ -274,7 +309,14 @@ Proceed to Step 6 (Generate Tasks).
|
|
|
274
309
|
|
|
275
310
|
### Step 6: Generate tasks.md (After All Q&A Complete)
|
|
276
311
|
|
|
277
|
-
|
|
312
|
+
Ao gerar tasks, VARRER clarify.md por TODOS os `[TASK_SOURCE:*]` tags:
|
|
313
|
+
- Cada tag com tipo `user-req` → task obrigatoria
|
|
314
|
+
- Cada tag com tipo `ai-suggestion` (aceita) → task obrigatoria
|
|
315
|
+
- Cada tag com tipo `decision` → task para implementar decisao
|
|
316
|
+
- Cada tag com tipo `edge-case` → task de validacao/protecao
|
|
317
|
+
- Cada tag com tipo `constraint` → task de teste negativo
|
|
318
|
+
|
|
319
|
+
Based on all decisions and TASK_SOURCE tags, create tasks:
|
|
278
320
|
|
|
279
321
|
```markdown
|
|
280
322
|
# Tasks - Migration 001
|
|
@@ -593,6 +635,9 @@ For automated workflows, use the SEDD CLI:
|
|
|
593
635
|
# Create new migration (creates clarify.md, tasks.md, decisions.md)
|
|
594
636
|
sedd clarify
|
|
595
637
|
|
|
638
|
+
# Create migration pre-populated from a GitHub issue
|
|
639
|
+
sedd clarify --from-issue https://github.com/owner/repo/issues/42
|
|
640
|
+
|
|
596
641
|
# Add tasks to current migration
|
|
597
642
|
sedd tasks '[{"story":"US1","description":"Task description"}]'
|
|
598
643
|
|
|
@@ -603,4 +648,24 @@ sedd complete T001-001
|
|
|
603
648
|
sedd status
|
|
604
649
|
```
|
|
605
650
|
|
|
651
|
+
**Options:**
|
|
652
|
+
- `--from-issue <url>` - Pre-populate clarify.md with context from a GitHub issue
|
|
653
|
+
|
|
654
|
+
### --from-issue Flow
|
|
655
|
+
|
|
656
|
+
When `--from-issue` is provided:
|
|
657
|
+
|
|
658
|
+
1. Fetches issue title and body from GitHub
|
|
659
|
+
2. **Downloads images** from the issue body to `{migration}/assets/` and rewrites links to relative paths (e.g. `./assets/image-001.png`), so the AI can see the visual content via Read tool
|
|
660
|
+
3. Pre-populates `clarify.md` with:
|
|
661
|
+
- `## Context (from GitHub Issue #N)` containing the issue body (with local image paths)
|
|
662
|
+
- `## Expected Outcome` set to the issue title
|
|
663
|
+
4. Links migration to the issue in `.github-sync.json`
|
|
664
|
+
5. Comments on the issue: "SEDD migration {id} started from this issue"
|
|
665
|
+
|
|
666
|
+
Supported image formats: `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`, and any `github.com/user-attachments` URL.
|
|
667
|
+
If a download fails, the original URL link is kept.
|
|
668
|
+
|
|
669
|
+
**Requires:** `gh` CLI installed and authenticated. GitHub integration (`sedd github setup`) needed for board/comment features.
|
|
670
|
+
|
|
606
671
|
Scripts also available in `.sedd/scripts/powershell/` and `.sedd/scripts/bash/`.
|
package/commands/sedd.specify.md
CHANGED
|
@@ -20,7 +20,11 @@ User runs `/sedd.specify "feature description"` or `/sedd.specify` (interactive)
|
|
|
20
20
|
|
|
21
21
|
3. **Check for existing feature branch**
|
|
22
22
|
- If on feature branch (###-name): use existing feature
|
|
23
|
-
- If
|
|
23
|
+
- If on master/main or outra branch nao-feature:
|
|
24
|
+
1. Determinar proximo feature ID (buscar maior ###- nas branches + 1)
|
|
25
|
+
2. Criar branch `{id}-{nome}` com `git checkout -b {id}-{nome}`
|
|
26
|
+
3. Confirmar: "Criei a branch {id}-{nome} e ja estou nela"
|
|
27
|
+
4. SO ENTAO prosseguir com criacao da estrutura
|
|
24
28
|
|
|
25
29
|
## Configuration
|
|
26
30
|
|
|
@@ -189,6 +193,9 @@ sedd specify 024 dark-mode-toggle -d "Add dark mode support"
|
|
|
189
193
|
# Create with expectation (recommended)
|
|
190
194
|
sedd specify 024 dark-mode-toggle -d "Add dark mode support" -e "User can toggle dark mode"
|
|
191
195
|
|
|
196
|
+
# Create from GitHub issue (reads title, body, labels)
|
|
197
|
+
sedd specify 042 from-issue --from-issue https://github.com/owner/repo/issues/42
|
|
198
|
+
|
|
192
199
|
# Check structure
|
|
193
200
|
sedd check
|
|
194
201
|
|
|
@@ -199,5 +206,24 @@ sedd status
|
|
|
199
206
|
**Options:**
|
|
200
207
|
- `-d, --description` - Feature description
|
|
201
208
|
- `-e, --expectation` - Expected outcome (used for alignment verification)
|
|
209
|
+
- `--from-issue <url>` - Create feature from a GitHub issue URL
|
|
210
|
+
|
|
211
|
+
### --from-issue Flow
|
|
212
|
+
|
|
213
|
+
When `--from-issue` is provided:
|
|
214
|
+
|
|
215
|
+
1. Fetches issue title, body, and labels from GitHub
|
|
216
|
+
2. Uses issue title as feature name (if feature-name is `from-issue` or `_`)
|
|
217
|
+
3. Extracts acceptance criteria from issue body (if present)
|
|
218
|
+
4. Creates branch, spec.md, interfaces.ts, _meta.json
|
|
219
|
+
5. **Downloads images** from the issue body to `assets/` and rewrites links to relative paths (e.g. `./assets/image-001.png`), so the AI can see the visual content via Read tool
|
|
220
|
+
6. Saves `sourceIssue` in `_meta.json` (permanent link)
|
|
221
|
+
7. Moves issue to "In Progress" on the GitHub project board
|
|
222
|
+
8. Comments on the issue: "SEDD feature created from this issue"
|
|
223
|
+
|
|
224
|
+
Supported image formats: `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`, and any `github.com/user-attachments` URL.
|
|
225
|
+
If a download fails, the original URL link is kept.
|
|
226
|
+
|
|
227
|
+
**Requires:** `gh` CLI installed and authenticated. GitHub integration (`sedd github setup`) needed for board/comment features.
|
|
202
228
|
|
|
203
229
|
Scripts also available in `.sedd/scripts/powershell/sedd-specify.ps1` and `.sedd/scripts/bash/sedd-specify.sh`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/cli/board.ts"],"names":[],"mappings":"AAQA,UAAU,YAAY;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+FrE"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import { loadConfig } from '../types/index.js';
|
|
6
|
+
import { GitOperations } from '../utils/git.js';
|
|
7
|
+
import { BoardManager } from '../core/board-manager.js';
|
|
8
|
+
export async function board(options = {}) {
|
|
9
|
+
const cwd = process.cwd();
|
|
10
|
+
const config = loadConfig(cwd);
|
|
11
|
+
const git = new GitOperations(cwd);
|
|
12
|
+
const bm = new BoardManager(config, cwd);
|
|
13
|
+
const specsDir = join(cwd, config.specsDir);
|
|
14
|
+
if (!existsSync(specsDir)) {
|
|
15
|
+
console.log(chalk.yellow('No specs directory found. Run "sedd init" first.'));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (options.move) {
|
|
19
|
+
const args = process.argv;
|
|
20
|
+
const moveIdx = args.indexOf('--move');
|
|
21
|
+
const taskId = args[moveIdx + 1];
|
|
22
|
+
const targetColumn = args[moveIdx + 2];
|
|
23
|
+
if (!taskId || !targetColumn) {
|
|
24
|
+
console.log(chalk.red('Usage: sedd board --move <task-id> "<column>"'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const { featureDir, meta } = getFeatureContext(cwd, config, git);
|
|
28
|
+
if (!featureDir || !meta)
|
|
29
|
+
return;
|
|
30
|
+
const success = bm.moveTask(featureDir, meta, taskId, targetColumn);
|
|
31
|
+
if (!success) {
|
|
32
|
+
console.log(chalk.red(`Failed to move ${taskId}`));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log(chalk.green(`✓ Moved ${taskId} to "${targetColumn}"`));
|
|
36
|
+
if (bm.isGitHubEnabled()) {
|
|
37
|
+
const autoSync = config.github?.autoSync || 'ask';
|
|
38
|
+
if (autoSync === 'off')
|
|
39
|
+
return;
|
|
40
|
+
if (autoSync === 'ask') {
|
|
41
|
+
const { shouldSync } = await inquirer.prompt([{
|
|
42
|
+
type: 'confirm',
|
|
43
|
+
name: 'shouldSync',
|
|
44
|
+
message: 'Sync this change to GitHub?',
|
|
45
|
+
default: true,
|
|
46
|
+
}]);
|
|
47
|
+
if (!shouldSync)
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const result = bm.syncToGitHub(featureDir, meta);
|
|
51
|
+
if (result.moved > 0 || result.synced > 0) {
|
|
52
|
+
console.log(chalk.green(`✓ Synced to GitHub`));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (options.sync) {
|
|
58
|
+
const { featureDir, meta } = getFeatureContext(cwd, config, git);
|
|
59
|
+
if (!featureDir || !meta)
|
|
60
|
+
return;
|
|
61
|
+
if (!bm.isGitHubEnabled()) {
|
|
62
|
+
console.log(chalk.yellow('GitHub sync not enabled. Run "sedd github setup" first.'));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
console.log(chalk.cyan('Syncing board with GitHub...'));
|
|
66
|
+
const result = bm.syncToGitHub(featureDir, meta);
|
|
67
|
+
console.log(chalk.green(`✓ Synced: ${result.synced} | Created: ${result.created} | Moved: ${result.moved}`));
|
|
68
|
+
if (result.errors.length > 0) {
|
|
69
|
+
result.errors.forEach(e => console.log(chalk.yellow(` ⚠ ${e}`)));
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (options.all) {
|
|
74
|
+
showAllBoards(cwd, config, bm, options.json);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const { featureDir, meta } = getFeatureContext(cwd, config, git);
|
|
78
|
+
if (!featureDir || !meta)
|
|
79
|
+
return;
|
|
80
|
+
const boardStatus = bm.getBoard(featureDir, meta);
|
|
81
|
+
if (!boardStatus) {
|
|
82
|
+
console.log(chalk.yellow('No active migration with tasks. Run "sedd clarify" then "sedd tasks" first.'));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (options.json) {
|
|
86
|
+
console.log(JSON.stringify(boardStatus, null, 2));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
renderBoard(boardStatus, bm, config);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function getFeatureContext(cwd, config, git) {
|
|
93
|
+
const specsDir = join(cwd, config.specsDir);
|
|
94
|
+
let currentFeature = null;
|
|
95
|
+
if (git.hasGit()) {
|
|
96
|
+
const branch = git.getCurrentBranch();
|
|
97
|
+
if (git.isFeatureBranch(branch)) {
|
|
98
|
+
const featureDir = join(specsDir, branch);
|
|
99
|
+
if (existsSync(featureDir)) {
|
|
100
|
+
currentFeature = branch;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!currentFeature) {
|
|
105
|
+
const features = readdirSync(specsDir, { withFileTypes: true })
|
|
106
|
+
.filter(d => d.isDirectory() && /^\d{3}-/.test(d.name))
|
|
107
|
+
.map(d => d.name)
|
|
108
|
+
.sort()
|
|
109
|
+
.reverse();
|
|
110
|
+
if (features.length > 0) {
|
|
111
|
+
currentFeature = features[0];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!currentFeature) {
|
|
115
|
+
console.log(chalk.yellow('No features found.'));
|
|
116
|
+
return { featureDir: null, meta: null };
|
|
117
|
+
}
|
|
118
|
+
const featureDir = join(specsDir, currentFeature);
|
|
119
|
+
const metaPath = join(featureDir, '_meta.json');
|
|
120
|
+
if (!existsSync(metaPath)) {
|
|
121
|
+
console.log(chalk.yellow(`No _meta.json for feature ${currentFeature}`));
|
|
122
|
+
return { featureDir: null, meta: null };
|
|
123
|
+
}
|
|
124
|
+
const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
|
|
125
|
+
return { featureDir, meta };
|
|
126
|
+
}
|
|
127
|
+
function showAllBoards(cwd, config, bm, json) {
|
|
128
|
+
const specsDir = join(cwd, config.specsDir);
|
|
129
|
+
const features = readdirSync(specsDir, { withFileTypes: true })
|
|
130
|
+
.filter(d => d.isDirectory() && /^\d{3}-/.test(d.name))
|
|
131
|
+
.map(d => d.name)
|
|
132
|
+
.sort();
|
|
133
|
+
if (features.length === 0) {
|
|
134
|
+
console.log(chalk.yellow('No features found.'));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const allBoards = [];
|
|
138
|
+
for (const feature of features) {
|
|
139
|
+
const featureDir = join(specsDir, feature);
|
|
140
|
+
const metaPath = join(featureDir, '_meta.json');
|
|
141
|
+
if (!existsSync(metaPath))
|
|
142
|
+
continue;
|
|
143
|
+
const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
|
|
144
|
+
const boardStatus = bm.getBoard(featureDir, meta);
|
|
145
|
+
if (boardStatus) {
|
|
146
|
+
allBoards.push(boardStatus);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (json) {
|
|
150
|
+
console.log(JSON.stringify(allBoards, null, 2));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (allBoards.length === 0) {
|
|
154
|
+
console.log(chalk.yellow('No active boards found.'));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
for (const boardStatus of allBoards) {
|
|
158
|
+
renderBoard(boardStatus, bm, config);
|
|
159
|
+
console.log('');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function renderBoard(boardStatus, bm, config) {
|
|
163
|
+
console.log(chalk.cyan.bold(`\nKanban: ${boardStatus.featureName} (Migration ${boardStatus.migrationId})\n`));
|
|
164
|
+
const colWidth = 22;
|
|
165
|
+
const headers = boardStatus.columns.map(col => {
|
|
166
|
+
const countStr = col.wipLimit
|
|
167
|
+
? `[${col.tasks.length}/${col.wipLimit}]`
|
|
168
|
+
: `[${col.tasks.length}]`;
|
|
169
|
+
const header = `${col.name} ${countStr}`;
|
|
170
|
+
return header.padEnd(colWidth);
|
|
171
|
+
});
|
|
172
|
+
console.log(chalk.bold(headers.join(' ')));
|
|
173
|
+
const separators = boardStatus.columns.map(() => '─'.repeat(colWidth));
|
|
174
|
+
console.log(chalk.gray(separators.join(' ')));
|
|
175
|
+
const maxRows = Math.max(...boardStatus.columns.map(c => c.tasks.length));
|
|
176
|
+
for (let i = 0; i < maxRows; i++) {
|
|
177
|
+
const cells = boardStatus.columns.map(col => {
|
|
178
|
+
const task = col.tasks[i];
|
|
179
|
+
if (!task)
|
|
180
|
+
return ' '.repeat(colWidth);
|
|
181
|
+
const text = `${task.id} ${truncate(task.description, colWidth - task.id.length - 2)}`;
|
|
182
|
+
return text.padEnd(colWidth);
|
|
183
|
+
});
|
|
184
|
+
console.log(cells.join(' '));
|
|
185
|
+
}
|
|
186
|
+
if (maxRows === 0) {
|
|
187
|
+
console.log(chalk.gray(' (no tasks)'));
|
|
188
|
+
}
|
|
189
|
+
const violations = bm.checkWipLimits(boardStatus);
|
|
190
|
+
if (violations.length > 0) {
|
|
191
|
+
console.log('');
|
|
192
|
+
for (const v of violations) {
|
|
193
|
+
console.log(chalk.red(`⚠ WIP: "${v.column}" has ${v.current}/${v.limit} items`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.log(chalk.gray('\nWIP: OK'));
|
|
198
|
+
}
|
|
199
|
+
const suggestions = bm.suggestNext(boardStatus);
|
|
200
|
+
if (suggestions.length > 0) {
|
|
201
|
+
const top = suggestions[0];
|
|
202
|
+
console.log(chalk.cyan(`Next: ${top.taskId} "${truncate(top.description, 40)}" (${top.reason})`));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function truncate(str, maxLen) {
|
|
206
|
+
const clean = str.replace(/\[[\w-]+\]\s*/g, '');
|
|
207
|
+
if (clean.length <= maxLen)
|
|
208
|
+
return clean;
|
|
209
|
+
return clean.substring(0, maxLen - 3) + '...';
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=board.js.map
|