@brunosps00/dev-workflow 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +2 -2
  3. package/lib/constants.js +6 -4
  4. package/lib/install-deps.js +22 -1
  5. package/lib/install-open-design.js +89 -0
  6. package/package.json +4 -2
  7. package/scaffold/en/commands/dw-adr.md +49 -11
  8. package/scaffold/en/commands/dw-analyze-project.md +5 -0
  9. package/scaffold/en/commands/dw-brainstorm.md +103 -32
  10. package/scaffold/en/commands/dw-claude-run.md +8 -5
  11. package/scaffold/en/commands/dw-help.md +3 -1
  12. package/scaffold/en/commands/dw-open-design.md +324 -0
  13. package/scaffold/en/commands/dw-plan.md +34 -5
  14. package/scaffold/en/templates/adr-template.md +8 -4
  15. package/scaffold/en/templates/idea-onepager.md +44 -2
  16. package/scaffold/pt-br/commands/dw-adr.md +49 -11
  17. package/scaffold/pt-br/commands/dw-analyze-project.md +5 -0
  18. package/scaffold/pt-br/commands/dw-brainstorm.md +105 -32
  19. package/scaffold/pt-br/commands/dw-claude-run.md +8 -5
  20. package/scaffold/pt-br/commands/dw-help.md +3 -1
  21. package/scaffold/pt-br/commands/dw-open-design.md +323 -0
  22. package/scaffold/pt-br/commands/dw-plan.md +34 -5
  23. package/scaffold/pt-br/templates/adr-template.md +8 -4
  24. package/scaffold/pt-br/templates/idea-onepager.md +44 -2
  25. package/scaffold/scripts/open-design/capture-current.mjs +170 -0
  26. package/scaffold/scripts/open-design/gate-prototype.mjs +223 -0
  27. package/scaffold/skill-registry.json +25 -1
  28. package/scaffold/skills/dw-cli-run/SKILL.md +10 -8
  29. package/scaffold/skills/dw-domain-modeling/SKILL.md +84 -0
  30. package/scaffold/skills/dw-domain-modeling/references/adr-policy.md +48 -0
  31. package/scaffold/skills/dw-domain-modeling/references/glossary-format.md +66 -0
  32. package/scaffold/skills/dw-grilling/SKILL.md +98 -0
  33. package/scaffold/skills/dw-grilling/references/decision-tree.md +56 -0
  34. package/scaffold/skills/dw-grilling/references/interview-loop.md +52 -0
@@ -0,0 +1,323 @@
1
+ <system_instructions>
2
+ Voce e o **runner headless do Open Design (`od`)** para gerar e iterar prototipos HTML em uma pasta de projeto,
3
+ sem abrir Electron e sem depender do estado da GUI do usuario. Use o daemon do `nexu-io/open-design` em
4
+ `--headless`, importe a pasta alvo uma vez, rode briefs single ou batch em serie, verifique o arquivo produzido,
5
+ rode gate visual Playwright/Firefox e **PARE para o gate do dono** antes de qualquer commit.
6
+
7
+ <critical>NUNCA use o estado da GUI do usuario. Sempre rode com `OD_DATA_DIR` isolado por projeto, por exemplo `.dw/.open-design/data/`.</critical>
8
+ <critical>NUNCA commite prototipo reprovado. O gate e dual >=9: gate automatico + avaliacao visual propria >=9, depois gate do dono.</critical>
9
+ <critical>O agente (`codex` ou `claude`) deve ser sempre explicito em `od run start --agent <agent>`. Se o usuario nao passar, resolva de config/estado do projeto; fallback `codex`.</critical>
10
+ <critical>NUNCA despache o pedido cru do usuario para o `od`. O valor deste comando e refinar o prompt primeiro: ancore no codigo real, estruture o brief, qualifique estados/temas/a11y/deep-link, persista o brief revisavel e so entao anexe o apendice headless.</critical>
11
+
12
+ ## Inputs
13
+
14
+ | Flag/argumento | Default | Descricao |
15
+ |---|---:|---|
16
+ | `--target <dir>` | `open-design/` | Pasta importada como projeto externo e onde os HTMLs serao escritos. |
17
+ | `--brief <file>` | nenhum | Um brief markdown para uma run single. |
18
+ | `--brief-glob <glob>` | nenhum | Batch em serie. Expanda para lista estavel e rode um prompt por vez. |
19
+ | `--output <file>` | obrigatorio no brief/apendice | HTML esperado; verifique no filesystem depois da run. |
20
+ | `--agent <codex|claude>` | estado/config -> `codex` | Agente repassado ao `od run start --agent`. |
21
+ | `--platform <text>` | `Web responsivo desktop-first e mobile-safe` | Resposta pre-preenchida para o discovery da skill `web-prototype`. |
22
+ | `--deep-link-id <id>` | nenhum | Valor usado no gate comportamental `?aberto=<id>` + Esc. |
23
+ | `--refactor` | falso | Modo redesign/refactor de tela existente; captura prints atuais e ancora o brief no estado visivel + codigo real. |
24
+ | `--url <url>` | nenhum | URL de app rodando para capturar prints atuais via Playwright Firefox. |
25
+ | `--viewports <lista>` | `1440x900,375x812` | Viewports separados por virgula para `--refactor --url`; expanda conforme a dor (ex.: `1920x1080` para tabela larga). |
26
+ | `--screenshot <path>` | repetivel | Print atual ja capturado quando nao houver `--url`; copie para `_refs/<slug>/`. |
27
+
28
+ ## 0. Refinar o brief
29
+
30
+ Antes de qualquer pre-flight de daemon ou chamada ao `od`, transforme a intencao do usuario em um brief qualificado.
31
+ Nao envie a frase crua do usuario para o runner.
32
+
33
+ Contrato obrigatorio:
34
+
35
+ | Etapa | Exigencia |
36
+ |---|---|
37
+ | Ancorar na realidade | Se a tela existe, leia o codigo real dela: colunas, enums, acoes, estados, permissoes, contracts e dominio. Leia tambem design system, prototipos irmaos e guias de design do projeto. E proibido inventar campo, status ou acao. |
38
+ | Estruturar | Reescreva o pedido no esqueleto padrao abaixo, preenchendo paths reais e arquivo de saida exato. |
39
+ | Qualificar | Cubra loading/skeleton, empty/vazio, erro/falha, light + dark, a11y, limites do design system local (ex.: <=6 cards/filtros), responsividade e deep-link. |
40
+ | Persistir | Salve o brief refinado dentro do projeto, por exemplo `<target>/PROMPT-<slug>.md`. Ele e entregavel revisavel pelo dono, nao arquivo descartavel. |
41
+ | Revisar se ja vier pronto | Se o usuario trouxer um brief ja qualificado, faca uma revisao rapida por checklist, ajuste apenas lacunas e persista a versao final. |
42
+
43
+ Esqueleto padrao do brief refinado:
44
+
45
+ ```markdown
46
+ # <titulo da tela/prototipo>
47
+
48
+ Cole este brief no Open Design. Arquivo de saida exato: `<OUTPUT_FILE>`.
49
+
50
+ ## 1. Por que
51
+ <dor real do usuario/produto; problema observavel que este prototipo precisa resolver>
52
+
53
+ ## 2. Decisao de interacao
54
+ <padrao de navegacao, abertura, selecao, filtros, ordenacao, edicao e confirmacoes>
55
+
56
+ ## 3. Layout/lista
57
+ Tabela/lista baseada apenas em colunas REAIS:
58
+
59
+ | Coluna real | Origem/contract | Como aparece | Estado/limite |
60
+ |---|---|---|---|
61
+ | <nome> | <arquivo/API/schema> | <texto, badge, acao> | <truncate, vazio, erro> |
62
+
63
+ ## 4. Detalhe/acoes
64
+ <drawer/modal/pagina de detalhe; acoes contextuais permitidas por estado/permissao real>
65
+
66
+ ## 5. Fidelidade de dominio
67
+ Para o mock nao mentir: usar enums/status reais, dados de exemplo realistas no idioma do projeto e incluir estados raros/quebrados que existem no dominio.
68
+
69
+ ## 6. Direcao visual
70
+ <tokens, componentes, densidade, referencias herdadas, prototipos irmaos e limites do design system>
71
+
72
+ ## Entregar
73
+ - `<OUTPUT_FILE>`
74
+ - `<OUTPUT_FILE>.artifact.json` se houver sidecar
75
+ ```
76
+
77
+ So depois de persistir esse arquivo anexe o apendice headless em `.dw/.open-design/runs/` e despache a run.
78
+
79
+ ### 0R. Modo refactor/redesign
80
+
81
+ Quando `--refactor` estiver presente, a fase 0 continua obrigatoria. Prints complementam a ancoragem no codigo; eles
82
+ nao substituem leitura de contracts, enums, permissoes, estados, design system e prototipos irmaos.
83
+
84
+ Capture ou copie os prints atuais para dentro da pasta importada, em `_refs/<slug>/`, antes de persistir o brief:
85
+
86
+ ```bash
87
+ node .dw/scripts/open-design/capture-current.mjs \
88
+ --target "$TARGET_DIR" \
89
+ --slug "<slug>" \
90
+ --url "<url>" \
91
+ --viewports "1440x900,375x812"
92
+ ```
93
+
94
+ Sem URL de app rodando, aceite prints prontos repetindo `--screenshot`:
95
+
96
+ ```bash
97
+ node .dw/scripts/open-design/capture-current.mjs \
98
+ --target "$TARGET_DIR" \
99
+ --slug "<slug>" \
100
+ --screenshot "./antes-1440-light.png" \
101
+ --screenshot "./antes-375-dark.png"
102
+ ```
103
+
104
+ Regras de captura:
105
+
106
+ | Caso | Exigencia |
107
+ |---|---|
108
+ | Viewports | Default sensato: desktop `1440x900` + mobile `375x812`. O agente escolhe/expande conforme a dor: bug mobile inclui `375x812`; tabela larga inclui `1920x1080`; tablet/console inclui `768x1024`. |
109
+ | Temas | Capture light e dark quando aplicavel. O helper usa `light,dark` por default e grava nomes como `_refs/<slug>/atual-1440-light.png` e `_refs/<slug>/atual-375-dark.png`. |
110
+ | Caminho robusto | O agente do `od` le imagens do filesystem do projeto. Referencie caminhos relativos dentro do target; nao dependa de flag de imagem no `run start`. |
111
+ | Higiene | `_refs/` e material de referencia nao devem virar prototipo. Se o projeto-alvo versiona prototipos finais, documente limpeza ou adicione `<target>/_refs/` ao `.gitignore` conforme a convencao local. |
112
+
113
+ O brief refinado do modo refactor deve adicionar este bloco:
114
+
115
+ ```markdown
116
+ ## Referencias da tela atual
117
+ Abra e ANALISE os prints antes de escrever:
118
+ - `_refs/<slug>/atual-1440-light.png`
119
+ - `_refs/<slug>/atual-375-dark.png`
120
+
121
+ ## O que esta errado hoje
122
+ <dor apontando elementos visiveis nos prints: densidade, hierarquia, tabela, filtros, estados, contraste, mobile, etc.>
123
+
124
+ ## A ideia da mudanca
125
+ <o que muda e por que; decisao de interacao/visual proposta pelo usuario ou pelo agente apos ler codigo e prints>
126
+
127
+ ## Preservar
128
+ <fluxos, campos, permissoes, estados, copys, affordances e integracoes que nao podem mudar>
129
+ ```
130
+
131
+ ## Pre-flight
132
+
133
+ | Checagem | Acao |
134
+ |---|---|
135
+ | Resolver `od` | `OD_CLI_DIR` vence. Senao use `~/.dw/vendor/open-design`. Se `apps/daemon/bin/od.mjs` nao existir, pare e mande rodar `dev-workflow install-deps`. |
136
+ | Prerequisitos | O checkout do Open Design exige Node `~24` e pnpm `>=10.33`. Se faltarem, pare com instrucoes objetivas. |
137
+ | Estado isolado | Crie `.dw/.open-design/`, `.dw/.open-design/data/`, `.dw/.open-design/runs/` e `.dw/.open-design/state.json`. |
138
+ | Porta | Escolha porta livre em `127.0.0.1`; persista `daemonUrl` e `port` no state. |
139
+ | Daemon vivo | Se `od daemon status --daemon-url <url> --json` retornar `ok: true`, reuse. Senao inicie novo daemon. |
140
+
141
+ Comando base do daemon:
142
+
143
+ ```bash
144
+ OD_DATA_DIR="$PWD/.dw/.open-design/data" \
145
+ OD_CHAT_RUN_INACTIVITY_TIMEOUT_MS=1800000 \
146
+ node "$OD_DIR/apps/daemon/bin/od.mjs" daemon start \
147
+ --headless \
148
+ --host 127.0.0.1 \
149
+ --port "$PORT"
150
+ ```
151
+
152
+ Ruido conhecido: `codex_core::shell_snapshot` pode logar `ERROR` de sintaxe. Isso e benigno; nao aborte se a run
153
+ continua e o arquivo alvo e criado.
154
+
155
+ ## Import idempotente
156
+
157
+ Use `project import-folder` na pasta alvo resolvida absoluta. Default: `<repo>/open-design/`.
158
+
159
+ Persistir em `.dw/.open-design/state.json`:
160
+
161
+ ```json
162
+ {
163
+ "schema_version": "1.0",
164
+ "targetDir": "/abs/repo/open-design",
165
+ "projectId": "<project.id>",
166
+ "conversationId": "<conversationId>",
167
+ "daemonUrl": "http://127.0.0.1:<port>",
168
+ "port": 17556,
169
+ "agent": "codex"
170
+ }
171
+ ```
172
+
173
+ Se `projectId` existe no state e `od project info <id> --daemon-url <url> --json` funciona para o mesmo
174
+ `targetDir`, reuse. Caso contrario, reimporte:
175
+
176
+ ```bash
177
+ node "$OD_DIR/apps/daemon/bin/od.mjs" project import-folder "$TARGET_DIR" \
178
+ --daemon-url "$OD_URL" \
179
+ --name "$(basename "$TARGET_DIR")" \
180
+ --skill web-prototype \
181
+ --design-system default \
182
+ --json
183
+ ```
184
+
185
+ Capture `project.id` e `conversationId`; nao dependa de estado global do app.
186
+
187
+ ## Apendice headless obrigatorio
188
+
189
+ Anexe este bloco ao final de cada brief em um arquivo temporario dentro de `.dw/.open-design/runs/`.
190
+ Preencha `<PLATFORM>`, `<OUTPUT_FILE>` e referencias irma se houver.
191
+
192
+ ```markdown
193
+ ---
194
+
195
+ ## Apendice headless para Open Design
196
+
197
+ Plataforma-alvo: <PLATFORM>.
198
+
199
+ Nao faca discovery e nao faca perguntas. Nao emita `<question-form>`. Siga este brief com as respostas acima e
200
+ entregue arquivo primeiro.
201
+
202
+ Arquivo de saida obrigatorio: `<OUTPUT_FILE>`.
203
+
204
+ Contrato file-first:
205
+ - Escreva o HTML diretamente no filesystem do projeto, exatamente em `<OUTPUT_FILE>`.
206
+ - Nao altere arquivos existentes, exceto quando este prompt for explicitamente uma iteracao cirurgica sobre um arquivo alvo.
207
+ - Se precisar criar sidecar, mantenha `<OUTPUT_FILE>.artifact.json` coerente.
208
+ - Nao responda apenas com bloco `<artifact>` textual; run `succeeded` sem arquivo e falha.
209
+
210
+ Para evitar timeout headless:
211
+ - Escreva arquivos grandes em partes, com edicoes de aproximadamente 150 linhas por chamada.
212
+ - Mantenha progresso visivel ate finalizar o HTML.
213
+
214
+ Contexto de consistencia:
215
+ - Leia prototipos irmaos em `prototipos/` ou na pasta indicada no brief antes de definir padroes visuais.
216
+ - Preserve o sistema visual local quando houver referencia proxima.
217
+
218
+ Deep-link obrigatorio:
219
+ - Implemente `?aberto=<id>` para abrir o drawer/modal do item correto.
220
+ - Ao fechar com Esc ou acao de fechar, limpe o parametro com `history.replaceState`.
221
+ - O drawer/modal deve usar `role="dialog"` e atributos ARIA adequados.
222
+ - Inclua estados skeleton/loading, empty/vazio e erro/falha.
223
+ ```
224
+
225
+ ## Run single
226
+
227
+ Sempre passe `--agent` explicitamente:
228
+
229
+ ```bash
230
+ node "$OD_DIR/apps/daemon/bin/od.mjs" run start \
231
+ --daemon-url "$OD_URL" \
232
+ --project "$PROJECT_ID" \
233
+ --conversation "$CONVERSATION_ID" \
234
+ --agent "$AGENT" \
235
+ --skill web-prototype \
236
+ --design-system default \
237
+ --prompt-file "$PROMPT_WITH_APPENDIX" \
238
+ --follow \
239
+ --json | tee ".dw/.open-design/runs/<slug>.jsonl"
240
+ ```
241
+
242
+ Depois da run, confira o arquivo. **Nao aceite apenas status `succeeded`:**
243
+
244
+ ```bash
245
+ test -s "$TARGET_DIR/<OUTPUT_FILE>"
246
+ ```
247
+
248
+ Registre no JSONL ou em sidecar de auditoria: brief, prompt com apendice, agente, daemonUrl, projectId,
249
+ conversationId, output esperado, status final e resultado da verificacao do arquivo.
250
+
251
+ ## Batch
252
+
253
+ Para `--brief-glob`, expanda os briefs, ordene por nome e rode em serie. Pare no primeiro caso em que:
254
+
255
+ | Condicao | Resultado |
256
+ |---|---|
257
+ | run falha | `BLOCKED` com log JSONL |
258
+ | run diz sucesso mas arquivo nao existe ou esta vazio | `FINDINGS` e follow-up cirurgico ou `BLOCKED` |
259
+ | gate visual <9 | `FINDINGS`; iterar antes de continuar |
260
+
261
+ Nao rode prompts em paralelo no mesmo projeto `od`; preserve auditabilidade e contexto.
262
+
263
+ ## Iteracao cirurgica
264
+
265
+ Use follow-up run no mesmo `projectId`/`conversationId`, com prompt curto e arquivo alvo explicito:
266
+
267
+ ```bash
268
+ node "$OD_DIR/apps/daemon/bin/od.mjs" run start \
269
+ --daemon-url "$OD_URL" \
270
+ --project "$PROJECT_ID" \
271
+ --conversation "$CONVERSATION_ID" \
272
+ --agent "$AGENT" \
273
+ --skill web-prototype \
274
+ --design-system default \
275
+ --prompt-file ".dw/.open-design/runs/<slug>.followup.md" \
276
+ --follow \
277
+ --json | tee -a ".dw/.open-design/runs/<slug>.jsonl"
278
+ ```
279
+
280
+ O follow-up deve dizer: arquivo unico, mudanca exata, nao tocar prototipos irmaos, manter deep-link e estados.
281
+
282
+ ## Gate visual obrigatorio
283
+
284
+ Execute o gate automatico:
285
+
286
+ ```bash
287
+ node .dw/scripts/open-design/gate-prototype.mjs \
288
+ --file "$TARGET_DIR/<OUTPUT_FILE>" \
289
+ --deep-link-id "<id-real>" \
290
+ --expected-text "<texto-do-item>" \
291
+ --out ".dw/.open-design/gate/<slug>"
292
+ ```
293
+
294
+ O gate cobre:
295
+
296
+ | Camada | Exigencia |
297
+ |---|---|
298
+ | Estrutural | `<title>`, `aberto`, `replaceState`, `role=dialog`/ARIA, skeleton/loading, empty/vazio, erro/falha. |
299
+ | Screenshot | Firefox headless em light e dark, com `colorScheme` e `data-theme`. |
300
+ | Comportamental | `?aberto=<id>` abre o item certo; Esc fecha e limpa o parametro. |
301
+ | Avaliacao | Automatico PASS + sua nota visual >=9. Se abaixo de 9, faca follow-up cirurgico. |
302
+
303
+ Depois de passar, **pare para o gate do dono**. Nao commite ate o dono aprovar.
304
+
305
+ ## Armadilhas validadas
306
+
307
+ | Armadilha | Sintoma | Contorno obrigatorio |
308
+ |---|---|---|
309
+ | Discovery da `web-prototype` | Abre com `<question-form>` e encerra o turno; headless nao gera GenUI (`od ui list` vazio). | Anexar o apendice headless respondendo plataforma e proibindo perguntas/discovery. |
310
+ | Timeout de inatividade | HTML grande fica silencioso e o run morre perto de 10min. | `OD_CHAT_RUN_INACTIVITY_TIMEOUT_MS=1800000` no daemon + instruir escrita em partes de ~150 linhas. |
311
+ | `codex_core::shell_snapshot` | Loga `ERROR` de sintaxe no stream. | Tratar como ruido se a run prossegue e o arquivo final existe. |
312
+ | Estado da GUI | Config/agente/projetos vazam do app do usuario. | `OD_DATA_DIR` isolado sempre; `--agent`, `--skill` e `--design-system` explicitos. |
313
+
314
+ ## Structured Return
315
+
316
+ **Status:** `PASS` | `FINDINGS` | `BLOCKED` | `NOT_APPLICABLE`
317
+ **Scope:** pasta alvo, briefs executados, agente usado, projectId/conversationId.
318
+ **Evidence:** logs JSONL, arquivo(s) HTML verificados, gate JSON, screenshots light/dark.
319
+ **Artifacts:** paths dos prototipos e sidecars.
320
+ **Decisions:** defaults/overrides aplicados (`agent`, `target`, plataforma, porta).
321
+ **Risks:** qualquer gate abaixo de 9, arquivo nao gerado apesar de run succeeded, dependencia ausente.
322
+ **Next Step:** gate do dono, follow-up cirurgico necessario, ou comando de resume exato.
323
+ </system_instructions>
@@ -55,7 +55,36 @@ Claude Code e OpenCode podem usar agentes nativos. Codex e Copilot usam `.agents
55
55
 
56
56
  <critical>Quando uma ferramenta estruturada de entrevista/input do usuario estiver disponivel, `/dw-plan` DEVE usa-la para as perguntas de clarificacao de PRD e TechSpec. Nao rebaixe para chat comum por conveniencia. Se nenhuma ferramenta desse tipo existir no runtime, faca as mesmas perguntas no chat e registre explicitamente: `Ferramenta de entrevista estruturada indisponivel; usando fallback em chat.`</critical>
57
57
 
58
- A ferramenta e obrigatoria no planejamento porque preserva escolhas explicitas do usuario e impede o agent de responder as proprias perguntas. Cada estagio mantem sua propria cota: PRD exige 7+ perguntas de produto; TechSpec exige 7+ perguntas tecnicas.
58
+ A ferramenta e obrigatoria no planejamento porque preserva escolhas explicitas do usuario e impede o agent de responder as proprias perguntas.
59
+
60
+ ## Entrevista dirigida por cobertura (sem cotas fixas de perguntas)
61
+
62
+ <critical>`/dw-plan` NÃO faz um número fixo de perguntas. Cada estágio monta uma **coverage matrix** sobre suas dimensões obrigatórias, descobre fatos do repo/rules/intel/artefatos de domínio, **credita evidência já resolvida num handoff de Grill alinhado**, e então pergunta — uma decisão por vez — SOMENTE as dimensões que continuam descobertas. Nunca re-pergunte uma decisão de produto que o usuário já resolveu no Grill.</critical>
63
+
64
+ ### Handoff alinhado (do grill do `/dw-brainstorm`)
65
+
66
+ Antes do Stage 1, verifique se há um one-pager de ideia em `.dw/spec/ideas/<slug>.md` e o vocabulário canônico em `.dw/domain/**`.
67
+
68
+ <critical>Valide o handoff e FALHE FECHADO. Credite um handoff alinhado — i.e. suprima as perguntas de produto que suas decisões cobrem — SOMENTE quando TODAS valem:
69
+ - `schema_version: "1.1"`;
70
+ - `status: aligned`;
71
+ - `alignment.confirmed_by_user: true`;
72
+ - toda branch de dependência resolvida (nenhum nó de decisão aberto);
73
+ - contradições glossário/código fechadas;
74
+ - nenhuma entrada **bloqueante** resta em Remaining Decisions.
75
+ Se QUALQUER check falha — ou o arquivo está malformado, internamente inconsistente, `draft` ou `paused` — o one-pager é **input, não handoff confiável**: leia para contexto, mas trate todas as suas decisões como **descobertas** e pergunte normalmente. Nunca suprima uma pergunta de produto só pela força do `status: aligned`; `alignment.confirmed_by_user: true` e uma árvore resolvida, não-bloqueante e sem contradições também são exigidos.</critical>
76
+
77
+ Quando (e só quando) o handoff é totalmente válido:
78
+ - Carregue suas **Resolved Decisions**, **Evidence** e links de **Canonical Vocabulary**.
79
+ - Marque toda dimensão de PRD que essas decisões cobrem como **já coberta** (cite o one-pager como evidência) — NÃO re-pergunte.
80
+ - Só dimensões descobertas viram perguntas, uma por vez.
81
+
82
+ ### Coverage matrices
83
+
84
+ - **Dimensões do PRD:** objetivos, usuários-alvo, limites de escopo, métricas de sucesso, estratégia de rollout, pontos de integração, edge cases.
85
+ - **Dimensões do TechSpec:** domain placement, data flow, dependências, core interfaces, estratégia de testes, reuse-vs-build, integração multi-projeto (quando aplicável).
86
+
87
+ Para cada estágio: monte a matriz, marque cada dimensão `coberta` (fato descoberto ou evidência alinhada creditada) ou `descoberta`, e pergunte só as `descobertas` — uma decisão por turn, cada uma com resposta recomendada. **Decisões técnicas que um Grill de produto não cobriu ainda podem ser perguntadas durante o TechSpec** — Grill alinha vocabulário e decisões de produto, não o design técnico completo.
59
88
 
60
89
  ## Constitution Gate
61
90
 
@@ -78,11 +107,11 @@ Roda em modo padrão OU `plan prd`.
78
107
 
79
108
  ### Pré-requisitos
80
109
  - Ideia ou tópico do usuário.
81
- - (Opcional) one-pager de brainstorm em `.dw/spec/ideas/<slug>.md` via `/dw-brainstorm --onepager`.
110
+ - (Opcional) um one-pager de ideia do `/dw-brainstorm` em `.dw/spec/ideas/<slug>.md`. Se estiver `status: aligned` (schema `1.1`, de uma sessão de Grill), consuma como handoff — suas Resolved Decisions são creditadas, não re-perguntadas (ver Entrevista dirigida por cobertura).
82
111
 
83
112
  ### Comportamento obrigatório
84
113
 
85
- 1. **Perguntas de clarificação (MÍNIMO 7).** Antes de escrever qualquer coisa, use a ferramenta de entrevista estruturada quando disponivel para fazer 7+ perguntas cobrindo: objetivos, usuários-alvo, limites de escopo, métricas de sucesso, estratégia de rollout, pontos de integração, edge cases. Se a ferramenta estiver indisponivel, use fallback em chat e registre o fallback.
114
+ 1. **Coverage matrix sobre as dimensões do PRD** (objetivos, usuários-alvo, limites de escopo, métricas de sucesso, estratégia de rollout, pontos de integração, edge cases). Monte a matriz, credite evidência de handoff alinhado e fatos descobertos do repo, e pergunte SOMENTE as dimensões descobertas — uma decisão por vez, cada uma com resposta recomendada — usando a ferramenta de entrevista estruturada quando disponível (registre o fallback em chat caso contrário). Sem contagem fixa de perguntas; nunca re-pergunte uma decisão resolvida num one-pager alinhado.
86
115
  2. **Web search MÍNIMO 3 queries** para padrões de mercado, contexto regulatório, abordagens de competidores quando relevante.
87
116
  3. **Constitution alignment.** Cada requisito funcional (FR-N.M) inclui linha `Constitution Alignment: respects P-NNN, P-MMM` OU `no applicable principle: <motivo>`.
88
117
  4. **Awareness multi-projeto.** Se feature cruza projetos do workspace, consulte `.dw/rules/integrations.md` e documente escopo na seção "Projetos Impactados".
@@ -106,7 +135,7 @@ Roda em modo padrão (após aprovação do PRD) OU `plan techspec` OU `plan --fr
106
135
  ### Comportamento obrigatório
107
136
 
108
137
  1. **Hard gate: open questions do PRD.** Se `.dw/spec/prd-<feature>/prd.md` tem seção "Open Questions" com itens não resolvidos, PARE e peça pra usuário resolver primeiro.
109
- 2. **Perguntas de clarificação (MÍNIMO 7).** Use a ferramenta de entrevista estruturada quando disponivel para fazer perguntas tecnicas cobrindo: domain placement, data flow, dependências, core interfaces, estratégia de testes, reuse-vs-build, integração multi-projeto se aplicável. Se a ferramenta estiver indisponivel, use fallback em chat e registre o fallback.
138
+ 2. **Coverage matrix sobre as dimensões do TechSpec** (domain placement, data flow, dependências, core interfaces, estratégia de testes, reuse-vs-build, integração multi-projeto quando aplicável). Credite evidência de handoff alinhado e fatos descobertos, e pergunte SOMENTE as dimensões descobertas — uma decisão por vez — usando a ferramenta de entrevista estruturada quando disponível (registre o fallback em chat caso contrário). Decisões técnicas não cobertas por um Grill de produto ainda podem ser perguntadas aqui. Sem contagem fixa de perguntas.
110
139
  3. **Web search MÍNIMO 3 queries** + Context7 MCP para framework/library specifics.
111
140
  4. **Source grounding (`dw-source-grounding`).** Toda decisão de framework/library carrega `[source: <url>, version: X.Y, retrieved: YYYY-MM-DD]`.
112
141
  5. **Constitution gate.** Cada decisão arquitetural lista `Respects: P-NNN` ou `Deviates: P-NNN — justification: <slug ADR ou racional>`. Desvios de princípios `severity: high/critical` sem ADR → PARE.
@@ -187,7 +216,7 @@ Após plan completo, o diretório do PRD contém:
187
216
 
188
217
  ## Diretrizes finais
189
218
 
190
- - Cada estágio tem sua própria cota de perguntas de clarificação — não recicle. Estágios diferentes precisam de framing diferente. Use a ferramenta de entrevista estruturada sempre que disponivel.
219
+ - Cada estágio roda uma coverage matrix sobre suas próprias dimensões — sem cota fixa de perguntas. Credite evidência de handoff alinhado e fatos descobertos; pergunte só decisões descobertas, uma por vez. Estágios diferentes precisam de framing diferente. Use a ferramenta de entrevista estruturada sempre que disponivel.
191
220
  - Web search é obrigatório; Context7 MCP para libraries. Sem pular pra "acho que sei a versão mais recente."
192
221
  - Constitution gate roda na entrada de cada estágio; defaults são auto-instalados quando ausente (nunca bloqueia).
193
222
  - Os três estágios produzem Markdown commitado — esses são os artefatos canônicos de planejamento. Eles evoluem com a feature.
@@ -3,8 +3,9 @@ id: NNN
3
3
  status: Proposed
4
4
  title: [Título imperativo curto da decisão]
5
5
  date: YYYY-MM-DD
6
- prd: [slug do PRD, ex: prd-user-auth]
7
- schema_version: "1.0"
6
+ scope: repo | prd
7
+ prd: [slug do PRD para scope=prd, ex: prd-user-auth; "n/a" para scope=repo]
8
+ schema_version: "1.1"
8
9
  supersedes: null
9
10
  superseded_by: null
10
11
  ---
@@ -46,8 +47,11 @@ Proposed | Accepted | Deprecated | Superseded by ADR-XXX
46
47
 
47
48
  ## Related
48
49
 
49
- - PRD: `.dw/spec/[prd-slug]/prd.md`
50
- - TechSpec: `.dw/spec/[prd-slug]/techspec.md` (se aplicável)
50
+ <!-- scope=prd: linke o PRD/TechSpec dono. scope=repo: sem PRD dono — omita as linhas de PRD/TechSpec
51
+ (ou escreva "n/a") e linke `.dw/constitution.md` / `.dw/rules/` só quando genuinamente aplicáveis. -->
52
+
53
+ - PRD: `.dw/spec/[prd-slug]/prd.md` (só scope=prd; "n/a" para scope=repo)
54
+ - TechSpec: `.dw/spec/[prd-slug]/techspec.md` (se aplicável; só scope=prd)
51
55
  - Tasks afetadas: [lista de tasks, se aplicável]
52
56
  - ADRs relacionadas: [lista, se aplicável]
53
57
 
@@ -1,11 +1,19 @@
1
1
  ---
2
2
  type: idea-onepager
3
- schema_version: "1.0"
4
- status: draft
3
+ schema_version: "1.1"
4
+ status: draft | paused | aligned
5
5
  date: YYYY-MM-DD
6
6
  classification: improves | consolidates | new
7
+ alignment:
8
+ confirmed_by_user: false # true SOMENTE quando o usuário confirma explicitamente o shared understanding
9
+ confirmed_on: null # data ISO dessa confirmação
7
10
  ---
8
11
 
12
+ > **Schema 1.1.** O bloco `## Grill Alignment` abaixo é preenchido por uma sessão de grill do `/dw-brainstorm`. Sem
13
+ > Grill, deixe esse bloco vazio e mantenha `status: draft`. `status: aligned` é permitido SOMENTE quando cada branch
14
+ > de dependência está resolvida, contradições glossário/código estão fechadas, nenhuma decisão bloqueante resta, e o
15
+ > usuário confirmou explicitamente o shared understanding — senão use `draft` ou `paused`.
16
+
9
17
  # Ideia: [Título curto e imperativo]
10
18
 
11
19
  ## Problem Statement
@@ -81,6 +89,40 @@ Idealmente 2-4 stories. Se são mais de 5, provavelmente não é MVP.]
81
89
  - [Pergunta 1 que afeta escopo]
82
90
  - [Pergunta 2 que afeta prioridade]
83
91
 
92
+ ## Grill Alignment
93
+
94
+ _(schema 1.1 — preenchido por uma sessão de grill do `/dw-brainstorm`; consumido pelo `/dw-plan`, que NÃO re-pergunta decisões resolvidas. Deixe vazio para um one-pager sem grill.)_
95
+
96
+ ### Resolved Decisions
97
+
98
+ | Decisão | Recomendado | Escolhido | Alternativa rejeitada | Evidência |
99
+ |---------|-------------|-----------|-----------------------|-----------|
100
+ | [a decisão] | [o que o Grill recomendou] | [o que o usuário escolheu] | [a opção rejeitada + seu trade-off] | [fonte no one-pager/repo] |
101
+
102
+ ### Evidence
103
+
104
+ [Fatos descobertos durante o Grill no repo/rules/intel/docs — cada um com sua fonte (`path:line`, doc, ou query de intel) — usados em vez de perguntar ao usuário.]
105
+
106
+ - **[fato]** — fonte: `[path:line ou doc]`
107
+
108
+ ### Canonical Vocabulary
109
+
110
+ [Links para `.dw/domain/**` dos termos de que esta ideia depende. Não repita definições aqui — aponte para o glossário.]
111
+
112
+ - **[Termo]** → `.dw/domain/glossary.md#termo` (ou `.dw/domain/contexts/<slug>.md#termo` num projeto multi-contexto)
113
+
114
+ ### Remaining Decisions
115
+
116
+ [Decisões não-bloqueantes ainda abertas após o alinhamento, com seu dono. Uma decisão bloqueante significa que o one-pager NÃO está `aligned`.]
117
+
118
+ - **[decisão aberta]** — dono: [quem] — bloqueante? [não]
119
+
120
+ ### Alignment State
121
+
122
+ - **State:** `draft` | `paused` | `aligned`
123
+ - **Shared understanding confirmado pelo usuário:** [sim/não — `aligned` exige um sim explícito]
124
+ - **Por que não alinhado (se draft/paused):** [o nó bloqueante ou contradição não fechada que parou o alinhamento]
125
+
84
126
  ## Next Step
85
127
 
86
128
  Escolha UM:
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ function parseArgs(argv) {
7
+ const result = { screenshot: [] };
8
+ for (let index = 0; index < argv.length; index += 1) {
9
+ const token = argv[index];
10
+ if (!token.startsWith("--")) continue;
11
+ const [rawKey, inlineValue] = token.slice(2).split("=", 2);
12
+ const key = rawKey.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
13
+ if (inlineValue !== undefined) {
14
+ if (key === "screenshot") result.screenshot.push(inlineValue);
15
+ else result[key] = inlineValue;
16
+ continue;
17
+ }
18
+ const next = argv[index + 1];
19
+ if (!next || next.startsWith("--")) {
20
+ if (key === "screenshot") {
21
+ throw new Error("Missing value for --screenshot <path>.");
22
+ }
23
+ result[key] = true;
24
+ continue;
25
+ }
26
+ if (key === "screenshot") result.screenshot.push(next);
27
+ else result[key] = next;
28
+ index += 1;
29
+ }
30
+ return result;
31
+ }
32
+
33
+ async function importFirefox() {
34
+ try {
35
+ return (await import("@playwright/test")).firefox;
36
+ } catch {
37
+ try {
38
+ return (await import("playwright")).firefox;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+ }
44
+
45
+ function slugify(value) {
46
+ return (
47
+ String(value)
48
+ .toLowerCase()
49
+ .replace(/^https?:\/\//, "")
50
+ .replace(/[^a-z0-9]+/g, "-")
51
+ .replace(/^-+|-+$/g, "")
52
+ .slice(0, 70) || "screen"
53
+ );
54
+ }
55
+
56
+ function parseViewports(value) {
57
+ return String(value || "1440x900,375x812")
58
+ .split(",")
59
+ .map((entry) => {
60
+ const match = entry.trim().match(/^(\d{2,5})x(\d{2,5})$/);
61
+ if (!match) return null;
62
+ return { width: Number(match[1]), height: Number(match[2]) };
63
+ })
64
+ .filter(Boolean);
65
+ }
66
+
67
+ function parseThemes(value) {
68
+ return String(value || "light,dark")
69
+ .split(",")
70
+ .map((entry) => entry.trim().toLowerCase())
71
+ .filter((entry) => entry === "light" || entry === "dark");
72
+ }
73
+
74
+ function inferProvidedName(source, index) {
75
+ const base = path.basename(source, path.extname(source)).toLowerCase();
76
+ const width = base.match(/(?:^|[^0-9])(\d{3,5})(?:x\d{3,5})?(?:[^0-9]|$)/)?.[1];
77
+ const theme = base.includes("dark") ? "dark" : base.includes("light") ? "light" : "";
78
+ if (width && theme) return `atual-${width}-${theme}.png`;
79
+ if (width) return `atual-${width}-${String(index + 1).padStart(2, "0")}.png`;
80
+ return `atual-ref-${String(index + 1).padStart(2, "0")}.png`;
81
+ }
82
+
83
+ async function captureFromUrl(args, outDir) {
84
+ if (!args.url) return [];
85
+ const firefox = await importFirefox();
86
+ if (!firefox) {
87
+ throw new Error("Playwright is not installed. Run: npm i -D @playwright/test && npx playwright install firefox");
88
+ }
89
+
90
+ const viewports = parseViewports(args.viewports);
91
+ if (viewports.length === 0) {
92
+ throw new Error("No valid --viewports entries. Use comma-separated WIDTHxHEIGHT values, for example 1440x900,375x812.");
93
+ }
94
+ const themes = parseThemes(args.themes);
95
+ if (themes.length === 0) {
96
+ throw new Error("No valid --themes entries. Use light,dark or one of them.");
97
+ }
98
+
99
+ const browser = await firefox.launch({ headless: true });
100
+ const shots = [];
101
+ try {
102
+ for (const viewport of viewports) {
103
+ for (const theme of themes) {
104
+ const context = await browser.newContext({
105
+ colorScheme: theme,
106
+ viewport,
107
+ });
108
+ const page = await context.newPage();
109
+ await page.goto(String(args.url), { waitUntil: "networkidle" }).catch(() => page.goto(String(args.url)));
110
+ await page.evaluate((value) => {
111
+ document.documentElement.setAttribute("data-theme", value);
112
+ }, theme);
113
+ await page.waitForTimeout(300);
114
+ const target = path.join(outDir, `atual-${viewport.width}-${theme}.png`);
115
+ await page.screenshot({ path: target, fullPage: true });
116
+ shots.push({ source: String(args.url), viewport, theme, path: target });
117
+ await context.close();
118
+ }
119
+ }
120
+ } finally {
121
+ await browser.close();
122
+ }
123
+ return shots;
124
+ }
125
+
126
+ function copyProvidedScreenshots(args, outDir) {
127
+ return args.screenshot.map((source, index) => {
128
+ const resolved = path.resolve(String(source));
129
+ if (!fs.existsSync(resolved)) {
130
+ throw new Error(`Screenshot not found: ${resolved}`);
131
+ }
132
+ const target = path.join(outDir, inferProvidedName(resolved, index));
133
+ fs.copyFileSync(resolved, target);
134
+ return { source: resolved, path: target };
135
+ });
136
+ }
137
+
138
+ async function main() {
139
+ const args = parseArgs(process.argv.slice(2));
140
+ if (!args.url && args.screenshot.length === 0) {
141
+ throw new Error("Pass --url <app-url> or one or more --screenshot <path> values.");
142
+ }
143
+
144
+ const targetDir = path.resolve(String(args.target || "open-design"));
145
+ const slug = slugify(args.slug || args.url || "screen");
146
+ const outDir = path.resolve(String(args.out || path.join(targetDir, "_refs", slug)));
147
+ fs.mkdirSync(outDir, { recursive: true });
148
+
149
+ const copied = copyProvidedScreenshots(args, outDir);
150
+ const captured = await captureFromUrl(args, outDir);
151
+ const shots = [...copied, ...captured];
152
+
153
+ process.stdout.write(
154
+ `${JSON.stringify(
155
+ {
156
+ targetDir,
157
+ refsDir: outDir,
158
+ relativeRefs: shots.map((shot) => path.relative(targetDir, shot.path).split(path.sep).join("/")),
159
+ shots,
160
+ },
161
+ null,
162
+ 2,
163
+ )}\n`,
164
+ );
165
+ }
166
+
167
+ main().catch((error) => {
168
+ process.stderr.write(`capture-current: ${error.message}\n`);
169
+ process.exit(1);
170
+ });